There are many QR code tools and SDKs available on the market. For Android development, Google ML Kit is no doubt a good choice, which is free and supports general QR code detection. However, it cannot satisfy the requirement of high density QR code detection. As a commercial barcode SDK, Dynamsoft Barcode Reader can cover special barcode types. In this article, we will simplify the sample of ML Kit and integrate it with Dynamsoft Barcode SDK to compare the performance of recognizing high density QR Code between ML Kit and Dynamsoft Barcode Reader.
Barcode SDK Download
-
ML Kit:
In
AndroidManifest.xml
, add:
<meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="barcode"/>
In
build.gradle
, add:
dependencies { implementation 'com.google.mlkit:barcode-scanning:17.0.0' // Or comment the dependency above and uncomment the dependency below to // use unbundled model that depends on Google Play Services // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:16.2.1' }
You can find the model file in generated apk file
apk/assets/mlkit_barcode_models/barcode_ssd_mobilenet_v1_dmp25_quant.tflite
. -
Dynamsoft Barcode Reader
Dynamsoft Barcode Reader 30-day Trial
Extract the SDK package and copy the
DynamsoftBarcodeReaderAndroid.aar
file to the libs folder of the project. Inbuild.gradle
, add:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) }
Alternatively, you can configure the Maven repository in
build.gradle
file as follows:
allprojects { repositories { google() jcenter() maven { url "https://download2.dynamsoft.com/maven/dbr/aar" } } } dependencies { implementation 'com.dynamsoft:dynamsoftbarcodereader:8.8.0@aar' }
Reading QR Code from Still Images
QR Code Scanning with Google ML Kit
Download the sample code of ML Kit vision.
It is an excellent sample app that features object detection, face detection, text recognition, barcode scanning, image labeling, custom image labeling, pose detection, and selfie segmentation.
To focus on still image detection, we only keep the StillImageActivity
and set it as the LAUNCHER
in AndroidManifest.xml
:
<activity
android:name=".java.StillImageActivity"
android:exported="true"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
QR Code Scanning with Dynamsoft's SDK
We create a dynamsoftbarcodescanner
folder and two class files: DynamsoftBarcodeGraphic.java
and DynamsoftBarcodeProcessor.java
.
The DynamsoftBarcodeGraphic
class is used to draw the detection results:
@Override
public void draw(Canvas canvas) {
if (result == null) {
throw new IllegalStateException("Attempting to draw a null barcode.");
}
// Draws the bounding box around the BarcodeBlock.
Point[] points = result.localizationResult.resultPoints;
int minx = points[0].x;
int miny = points[0].y;
int maxx = points[0].x;
int maxy = points[0].y;
for (int i = 1; i < 4; i++) {
if (points[i].x < minx) {
minx = points[i].x;
}
else if (points[i].x > maxx) {
maxx = points[i].x;
}
if (points[i].y < miny) {
miny = points[i].y;
}
else if (points[i].y > maxy) {
maxy = points[i].y;
}
}
RectF rect = new RectF(minx, miny, maxx, maxy);
// If the image is flipped, the left will be translated to right, and the right to left.
float x0 = translateX(rect.left);
float x1 = translateX(rect.right);
rect.left = min(x0, x1);
rect.right = max(x0, x1);
rect.top = translateY(rect.top);
rect.bottom = translateY(rect.bottom);
canvas.drawRect(rect, rectPaint);
// Draws other object info.
float lineHeight = TEXT_SIZE + (2 * STROKE_WIDTH);
float textWidth = barcodePaint.measureText(result.barcodeText);
canvas.drawRect(
rect.left - STROKE_WIDTH,
rect.top - lineHeight,
rect.left + textWidth + (2 * STROKE_WIDTH),
rect.top,
labelPaint);
// Renders the barcode at the bottom of the box.
canvas.drawText(result.barcodeText, rect.left, rect.top - STROKE_WIDTH, barcodePaint);
}
The DynamsoftBarcodeProcessor
class is used to decode QR code. As we load an image file, the processBitmap(Bitmap bitmap, final GraphicOverlay graphicOverlay)
function will be triggered in DynamsoftBarcodeProcessor.java
. Thereafter, we call decodeBufferedImage(bitmap, "")
to recognize QR code:
@Override
public void processBitmap(Bitmap bitmap, final GraphicOverlay graphicOverlay) {
try {
long frameStartMs = SystemClock.elapsedRealtime();
TextResult[] results = barcodeScanner.decodeBufferedImage(bitmap, "");
long frameEndMs = SystemClock.elapsedRealtime();
if (results != null) {
for (int i = 0; i < results.length; ++i) {
TextResult barcode = results[i];
graphicOverlay.add(new DynamsoftBarcodeGraphic(graphicOverlay, barcode));
}
graphicOverlay.add(
new InferenceInfoGraphic(
graphicOverlay,
frameEndMs - frameStartMs,
frameEndMs - frameStartMs,
null));
}
} catch (IOException e) {
e.printStackTrace();
} catch (BarcodeReaderException e) {
e.printStackTrace();
}
}
Build and run
Build and run the project in Android Studio:
High Density QR Code Detection Performance
Let's take some tests to see how ML Kit and Dynamsoft Barcode Reader perform for high density QR code images.
To make the test transparent and convincing, we use the public image dataset provided by boofcv.
The test images are located in qrcodes_v3/qrcodes/detection/high_version
.
We pick six images from the dataset and run the test on them.
It is surprising that ML Kit barcode scanning API is incompetent to these images. ML Kit took more time than Dynamsoft Barcode Reader, and recognized nothing. In contrast, Dynamsoft Barcode Reader is able to recognize all high density QR code images.