Long-Distance QR Code Scanning: Why Scanning Fails and How Resolution Helps

Let’s continue discussing scanning QR codes at a distance. In this article, we’ll talk about resolution.

What you’ll learn: why the live video stream limits how far a QR code can be read, how capturing at the camera’s highest resolution or taking a photo extends the range, and how image enhancement techniques - scale-up and super resolution - can rescue images whose modules are too small.

Key Takeaways

  • Live video streams often cap at 1080p even when the sensor supports more, and that pixel budget decides how far a code can be read; a photo uses the full sensor resolution and multiplies the scanning distance.
  • In the experiment with a 2x2 cm QR code on a monitor, the longest distance grew from 65 cm (live scan) to 130 cm (photo), while a 4x digital zoom and super resolution improved the live-scan range only slightly.
  • Scale-up enlarges small-module codes so the decoder can read them; in the current Capture Vision SDKs the ScaleUpModes parameter is configured through JSON parameter templates.
  • Super resolution (ESRGAN through TensorFlow Lite) can recover details of a blurry code, but the stock model accepts only 50x50 inputs and is not trained on QR code data, so results are limited.

Why It Fails

Even with zoom, a live scan is limited by the resolution of the video stream: most phones expose 1080p streams and only some support 4K, so a far-away code occupies very few pixels per module and the decoder cannot resolve it. The camera sensor itself can capture several times more detail - the gap between the video stream and the full sensor is exactly what the techniques in this article exploit.

Using the camera’s highest resolution

Most of the current smartphones’ video stream resolution can be set to 1080P (Full HD) and many of them support 4K (Ultra HD) video capturing. The higher the resolution we choose, the clearer the code can become so that it is easier to read.

However, although the native camera app can shoot a 4K video, a third-party camera app may only be able to shoot a 1080P one on many devices. The resolution of the video stream is not high enough to do a live scan of QR codes afar.

In such a case, we can take a photo first and then decode it. The resolution of a photo can be several times higher than the supported video stream resolution. This can significantly increase the scanning distance.

A QR code in video stream:

A QR code in a taken photo:

Try the resolution and enhancement techniques yourself with a 30-day free trial license.

Image enhancing

We can enhance the images to improve the resolution for a higher successful decoding rate.

Scale-Up

The code afar detected often has a low image resolution and the module size is very small.

We can scale up the image to increase the module size so that DBR can successfully read it.

Dynamsoft Barcode Reader provides a scaleUpModes parameter to do this. In the current Capture Vision SDKs, advanced parameters are set through parameter templates (JSON). For example, the ScaleUpModes parameter can be set to use linear interpolation as the scale-up mode and a ModuleSizeThreshold can be specified so that scale-up is applied when the module size is below the threshold. Refer to the parameter template documentation for the details of the template structure.

Using scale-up, it is possible to read the code below.

Super Resolution

Super Resolution can be used to recover details of images.

Here, we use TensorFlow’s super resolution example to process a blurry QR code image.

Code:

import tensorflow as tf
import cv2

lr = tf.io.read_file("small.jpg")
lr = tf.image.decode_jpeg(lr)
lr = tf.expand_dims(lr, axis=0)
lr = tf.cast(lr, tf.float32)
interpreter = tf.lite.Interpreter(model_path="ESRGAN.tflite")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
interpreter.set_tensor(input_details[0]['index'], lr)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
sr = tf.squeeze(output_data, axis=0)
sr = tf.clip_by_value(sr, 0, 255)
sr = tf.round(sr)
sr = tf.cast(sr, tf.uint8)
cv2.imwrite("4x.jpg",sr.numpy())

Before:

After:

The image is scaled up four times and the code becomes sharper.

It is possible to integrate it in an Android mobile app with TensorFlow-Lite.

But based on my personal experience, this super resolution model is not very useful as it limits the size of input images to 50x50. In addition, the default model is not trained against QR code datasets. Further works can be done like training a QR code super resolution model.

Experiment

I used my Sharp Aquos S2 to scan a QR code displayed on my monitor to do an experiment. The size of the code displayed is 2x2cm. We can get a rough idea of the effects of the methods mentioned above.

Longest Distance (cm) Condition Resolution
65 live scan without zoom 1920x1080
70 live scan with 4x digital zoom 1920x1080
80 live scan with super resolution 1920x1080
130 photo 3024x3024

We can use tangent to calculate the distance for different code sizes.

Camera and code

Distance calculation

For example, if the code size is 6x6cm, then the longest distance of live scan is 65*6/2=195cm.

Real-World Constraints

  • Photos beat video streams for distance. In the experiment, decoding a photo more than doubled the range compared with the live scan (130 cm vs 65 cm for a 2x2 cm code), because the photo resolution (3024x3024) far exceeded the 1080p stream.
  • The stock ESRGAN model is restrictive. It limits input images to 50x50 and is not trained on QR code data, so it helps only for small crops; a model trained on QR code datasets would be needed for reliable gains.
  • Scale-up cannot create detail that is not there. Enlarging pixels helps the decoder only when the code modules are still present in the image; heavy blur or compression artifacts remain a problem.
  • Device-dependent variables dominate. Maximum stream resolution, sensor resolution, and zoom capability differ per phone, so the distances above are specific to the Sharp Aquos S2 used in the experiment.

Common Issues & Edge Cases

  • The camera app offers 4K but the scanning app does not. Third-party apps often cap the video stream lower than the native camera app. Capture a photo through the app instead of relying on the live stream.
  • Scale-up or super resolution still cannot read the code. If the modules are smaller than the sensor can resolve or the image is too blurry, enhancement cannot recover the code. Combine zoom, photo capture, and enhancement and test the distance step by step.
  • Interpreting the distance numbers. The measured distances scale with the code size: for a 6x6 cm code, multiply the 2x2 cm results by three (for example about 195 cm for the live scan without zoom).

Source Code

Get the complete sample project source code on GitHub