Firebase launched ML Kit to recognize and decode barcodes(and much more). This article helps you to integrate bar-code detection using ML KIT.
1.Configure Build.gradle
dependencies {
implementation 'com.google.firebase:firebase-ml-vision:16.0.0'
}
2.Update Manifest file
Add the following declaration to your app’s AndroidManifest.xml
file under <application> to automatically download the ML model to the device after your app is installed from the Play Store.
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="barcode" />
3. Configure Bar-code Detector
If you know which barcode formats you expect to read, you can improve the speed of the barcode detector by configuring it to only detect those formats.
FirebaseVisionBarcodeDetectorOptions options =
new FirebaseVisionBarcodeDetectorOptions.Builder()
.setBarcodeFormats(
FirebaseVisionBarcode.FORMAT_QR_CODE,
FirebaseVisionBarcode.FORMAT_AZTEC)
.build();
The following formats are supported:
- Code 128 (
FORMAT_CODE_128
) - Code 39 (
FORMAT_CODE_39
) - Code 93 (
FORMAT_CODE_93
) - Codabar (
FORMAT_CODABAR
) - EAN-13 (
FORMAT_EAN_13
) - EAN-8 (
FORMAT_EAN_8
) - ITF (
FORMAT_ITF
) - UPC-A (
FORMAT_UPC_A
) - UPC-E (
FORMAT_UPC_E
) - QR Code (
FORMAT_QR_CODE
) - PDF417 (
FORMAT_PDF417
) - Aztec (
FORMAT_AZTEC
) - Data Matrix (
FORMAT_DATA_MATRIX
)
4. Create a FirebaseVisionImage
object from your image.
- To create a
FirebaseVisionImage
object from a Bitmap/ByteBuffer/ByteArray/File:
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(context, uri);
} catch (IOException e) {
e.printStackTrace();
}
To create a FirebaseVisionImage
object from a ByteBuffer
or a byte array, first calculate the image rotation as described below.
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
/**
* Get the angle by which an image must be rotated given the device's current
* orientation.
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private int getRotationCompensation(String cameraId, Activity activity, Context context)
throws CameraAccessException {
// Get the device's current rotation relative to its "native" orientation.
// Then, from the ORIENTATIONS table, look up the angle the image must be
// rotated to compensate for the device's rotation.
int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int rotationCompensation = ORIENTATIONS.get(deviceRotation);
// On most devices, the sensor orientation is 90 degrees, but for some
// devices it is 270 degrees. For devices with a sensor orientation of
// 270, rotate the image an additional 180 ((270 + 270) % 360) degrees.
CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
int sensorOrientation = cameraManager
.getCameraCharacteristics(cameraId)
.get(CameraCharacteristics.SENSOR_ORIENTATION);
rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360;
// Return the corresponding FirebaseVisionImageMetadata rotation value.
int result;
switch (rotationCompensation) {
case 0:
result = FirebaseVisionImageMetadata.ROTATION_0;
break;
case 90:
result = FirebaseVisionImageMetadata.ROTATION_90;
break;
case 180:
result = FirebaseVisionImageMetadata.ROTATION_180;
break;
case 270:
result = FirebaseVisionImageMetadata.ROTATION_270;
break;
default:
result = FirebaseVisionImageMetadata.ROTATION_0;
Log.e(TAG, "Bad rotation value: " + rotationCompensation);
}
return result;
}
Then, create a FirebaseVisionImageMetadata
object that contains the image's height, width, color encoding format, and rotation:
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setWidth(1280)
.setHeight(720)
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setRotation(rotation)
.build();
5. Get an instance of FirebaseVisionBarcodeDetector
:
FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance()
.getVisionBarcodeDetector();// Or, to specify the formats to recognize:
// FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance()
// .getVisionBarcodeDetector(options);
6. Finally, pass the image to the detectInImage
method:
Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)
.addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>() {
@Override
public void onSuccess(List<FirebaseVisionBarcode> barcodes) {
// Task completed successfully
// ...
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Task failed with an exception
// ...
}
});
7. Detected Bar-code Information:
If the barcode detector was able to determine the type of data encoded by the barcode, you can get an object containing parsed data.
for (FirebaseVisionBarcode barcode: barcodes) {
Rect bounds = barcode.getBoundingBox();
Point[] corners = barcode.getCornerPoints();
String rawValue = barcode.getRawValue();
int valueType = barcode.getValueType();
// See API reference for complete list of supported types
switch (valueType) {
case FirebaseVisionBarcode.TYPE_WIFI:
String ssid = barcode.getWifi().getSsid();
String password = barcode.getWifi().getPassword();
int type = barcode.getWifi().getEncryptionType();
break;
case FirebaseVisionBarcode.TYPE_URL:
String title = barcode.getUrl().getTitle();
String url = barcode.getUrl().getUrl();
break;
}
}
And that’s it, you are ready to scan Bar-Codes/QR Codes/Data Matrix codes using ML VISION no need to have deep knowledge of neural networks or model optimization to get started.