Scan High-Density QR Codes on Android Devices: Google ML Kit vs. Dynamsoft's SDK

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.

high density QR code from Google

This article is Part 4 in a 4-Part Series.

Barcode SDK Download

  • ML Kit:

    In AndroidManifest.xml, add:


    In build.gradle, add:

      dependencies {
          implementation ''
          // Or comment the dependency above and uncomment the dependency below to
          // use unbundled model that depends on Google Play Services
          // implementation ''

    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. In build.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 {
              maven {
                  url ""
      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:

        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>

QR Code Scanning with Dynamsoft’s SDK

We create a dynamsoftbarcodescanner folder and two class files: and

The DynamsoftBarcodeGraphic class is used to draw the detection results:

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); = translateY(;
    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);
            rect.left - STROKE_WIDTH,
   - lineHeight,
            rect.left + textWidth + (2 * STROKE_WIDTH),
    // Renders the barcode at the bottom of the box.
    canvas.drawText(result.barcodeText, rect.left, - 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 Thereafter, we call decodeBufferedImage(bitmap, "") to recognize QR code:

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));
                    new InferenceInfoGraphic(
                            frameEndMs - frameStartMs,
                            frameEndMs - frameStartMs,

    } catch (IOException e) {
    } catch (BarcodeReaderException e) {

Build and run

Build and run the project in Android Studio:

high density QR code detection

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.

high density QR detection comparison

Source Code

Search Blog Posts