androidgoogle-play-servicesqr-codeandroid-vision

Scan QRcode with inverted colors using Vision API


After struggling a few hours on making my app detect this QRCode:original QRCode

I realized that the problem was the in the QRCode appearance. After inverting the colors, the detection was working perfectly.inverted QRCode.

Is there a way to make Vision API detect the first QRCode? I tried to enable all symbologies but it did not work. I guess it is possible because the app QR Code Reader detects it.


Solution

  • I improved googles example app "barcode-reader" to detect both inverted colored barcodes and regular ones.

    here is a link to googles example app:

    https://github.com/googlesamples/android-vision/tree/master/visionSamples/barcode-reader

    I did so by editing "CameraSource" class, package: "com.google.android.gms.samples.vision.barcodereader.ui.camera".

    I added a parameter: private boolean isInverted = false;

    and changed function void setNextFrame(byte[] data, Camera camera):

    void setNextFrame(byte[] data, Camera camera) {
                synchronized (mLock) {
                    if (mPendingFrameData != null) {
                        camera.addCallbackBuffer(mPendingFrameData.array());
                        mPendingFrameData = null;
                    }
    
                    if (!mBytesToByteBuffer.containsKey(data)) {
                        Log.d(TAG,
                                "Skipping frame.  Could not find ByteBuffer associated with the image " +
                                        "data from the camera.");
                        return;
                    }
    
                    mPendingTimeMillis = SystemClock.elapsedRealtime() - mStartTimeMillis;
                    mPendingFrameId++;
                    if (!isInverted){
                        for (int y = 0; y < data.length; y++) {
                            data[y] = (byte) ~data[y];
                        }
                        isInverted = true;
                    } else {
                        isInverted = false;
                    }
                    mPendingFrameData = mBytesToByteBuffer.get(data);
    
                    // Notify the processor thread if it is waiting on the next frame (see below).
                    mLock.notifyAll();
                }
            }