Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't read a QR code from camera

Tags:

android

zxing

EDIT:

After playing around with it for a few hours, I came to believe that the problem is in the image quality. For example, to first image is how it came from the camera. Decoder can't read it. The second image is turned into B/W with adjusted contrast and the decoder reads it great.

Since the demo app that came with zxing is able to read the fist image off the monitor in a few seconds, I think the problem might be in some setting deep within the zxing library. It doesn't wait long enough to process the image, but spits out NotFound almost instantly.

enter image description here enter image description here


I'm making a simple QR-reader app. Here's a screenshot. The top black area is a surfaceview, that shows frames from the camera. It works fine, only you can't see it in the screenshot.

Then, when I press the button, a bitmap is taken from that surfaceview, placed on an ImageView below and is attempted to be read by the zxing library.

Yet it will give out a NotFoundException. :/

**10-17 19:53:15.382: WARN/System.err(2238): com.google.zxing.NotFoundException
10-17 19:53:15.382: WARN/dalvikvm(2238): getStackTrace() called but no trace available**

On the other hand, if I crop the qr image from this screenshot, place it into the imageview ( instead of a camera feed ) and try to decode it, it works fine. Therefor the QR image itself and its quality are OK... but then why doesn't it decode in the first scenario?

Thanks!

enter image description here

public void dec(View v)
{

ImageView ivCam2 = (ImageView)findViewById(R.id.imageView2);
ivCam2.setImageBitmap(bm);

BitmapDrawable drawable = (BitmapDrawable) ivCam2.getDrawable();
Bitmap bMap = drawable.getBitmap();

TextView textv = (TextView) findViewById(R.id.mytext);

LuminanceSource source = new RGBLuminanceSource(bMap); 
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
try {
     Result result = reader.decode(bitmap);
     Global.text = result.getText(); 
        byte[] rawBytes = result.getRawBytes(); 
        BarcodeFormat format = result.getBarcodeFormat(); 
        ResultPoint[] points = result.getResultPoints();
        textv.setText(Global.text);

} catch (NotFoundException e) {
    textv.setText("NotFoundException");
} catch (ChecksumException e) {
    textv.setText("ChecksumException");
} catch (FormatException e) {
    textv.setText("FormatException");
}  

}

how the bitmap is created:

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
    {
            try
            {
                    this.camera = Camera.open();
                    this.camera.setPreviewDisplay(this.holder);

                    this.camera.setPreviewCallback(new PreviewCallback() {

                      public void onPreviewFrame(byte[] _data, Camera _camera) {

                        Camera.Parameters params = _camera.getParameters();
                           int w = params.getPreviewSize().width;
                           int h = params.getPreviewSize().height;
                           int format = params.getPreviewFormat();
                           YuvImage image = new YuvImage(_data, format, w, h, null);

                           ByteArrayOutputStream out = new ByteArrayOutputStream();
                           Rect area = new Rect(0, 0, w, h);
                           image.compressToJpeg(area, 50, out);

                           bm = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());

                      }
                    });

            }
            catch(IOException ioe)
            {
                    ioe.printStackTrace(System.out);
            }
    }
like image 548
Roger Avatar asked Jun 03 '26 23:06

Roger


1 Answers

I wrote this code. Returning quickly isn't a problem. Decoding is very fast on a mobile, and very very fast on a desktop.

The general answer to this type of question is that some images just aren't going to decode. That's life -- the heuristics don't always get it right. But I don't think that is the problem here.

QR codes don't decode without a minimal white "quiet zone" around them. The image beyond its borders is considered white for this purpose. But in your raw camera image, there's little border around the code and it's not all considered white by the binarizer, I'd bet.

Still, there's more you can do. Set the TRY_HARDER hint to the decoder, for one, to have it spend a lot more CPU to try to decode. You can also try a different Binarizer implementation than the default HybridBinarizer.

(The rest looks just fine. I assume that RGBLuminanceSource is getting data in the format it expects; it ought to from Bitmap)

like image 183
Sean Owen Avatar answered Jun 06 '26 12:06

Sean Owen