Android Vision - Reduce Barcode Tracking Window

I am trying to embed the Google Visions crawler in the application I'm working on. By default, its full-screen activity and barcodes are tracked all over the screen.

However, I need a full-screen camera, but with a limited scan window. For example, the surface view of the camera should be full-screen, it has 2 transparent overlays set to 35% of the screen height above and below, leaving a 30% viewport in the center.

I changed the graphic overlay, so it will only be displayed in the middle viewport, but havent been able to determine how to limit barcode tracking in the same area.

Any ideas?

+6
source share
2 answers

The existing API does not provide the ability to limit the scan area. However, you can either filter the results coming out of the detector, or crop the image that is transferred to the detector.

Filter Results Approach

With this approach, a barcode detector will scan the entire image area, but detected barcodes outside the target area will be ignored. One way to do this is to implement a โ€œfocusing processorโ€ that receives results from the detector and passes no more than one barcode for your associated tracker. For instance:

public class CentralBarcodeFocusingProcessor extends FocusingProcessor<Barcode> { public CentralBarcodeFocusingProcessor(Detector<Barcode> detector, Tracker<Barcode> tracker) { super(detector, tracker); } @Override public int selectFocus(Detections<Barcode> detections) { SparseArray<Barcode> barcodes = detections.getDetectedItems(); for (int i = 0; i < barcodes.size(); ++i) { int id = barcodes.keyAt(i); if (/* barcode in central region */) { return id; } } return -1; } } 

Then you associate this processor with the detector as follows:

  BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).build(); barcodeDetector.setProcessor( new CentralBarcodeFocusingProcessor(myTracker)); 

Cropping Image Approach

First you need to crop the image before calling the detector. This can be done by implementing the Detector subclass, which wraps the barcode detector, truncates the received images, and causes a barcode scan with cropped images.

For example, you should make a detector to intercept and crop the image as follows:

 class MyDetector extends Detector<Barcode> { private Detector<Barcode> mDelegate; MyDetector(Detector<Barcode> delegate) { mDelegate = delegate; } public SparseArray<Barcode> detect(Frame frame) { // *** crop the frame here return mDelegate.detect(croppedFrame); } public boolean isOperational() { return mDelegate.isOperational(); } public boolean setFocus(int id) { return mDelegate.setFocus(id); } } 

You would wrap the barcode detector with this, placing it between the camera source and the barcode detector:

 BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context) .build(); MyDetector myDetector = new MyDetector(barcodeDetector); myDetector.setProcessor(/* include your processor here */); mCameraSource = new CameraSource.Builder(context, myDetector) .build(); 
+3
source

Based on @ pm0733464, answer the example of how to get the barcode closest to the preview center.

 public class CentralBarcodeFocusingProcessor extends FocusingProcessor<Barcode> { public CentralBarcodeFocusingProcessor(Detector<Barcode> detector, Tracker<Barcode> tracker) { super(detector, tracker); } @Override public int selectFocus(Detector.Detections<Barcode> detections) { SparseArray<Barcode> barcodes = detections.getDetectedItems(); Frame.Metadata meta = detections.getFrameMetadata(); double nearestDistance = Double.MAX_VALUE; int id = -1; for (int i = 0; i < barcodes.size(); ++i) { int tempId = barcodes.keyAt(i); Barcode barcode = barcodes.get(tempId); float dx = Math.abs((meta.getWidth() / 2) - barcode.getBoundingBox().centerX()); float dy = Math.abs((meta.getHeight() / 2) - barcode.getBoundingBox().centerY()); double distanceFromCenter = Math.sqrt((dx * dx) + (dy * dy)); if (distanceFromCenter < nearestDistance) { id = tempId; nearestDistance = distanceFromCenter; } } return id; } } 
+2
source

All Articles