Decode Micro QR codes with Python

Solution 1:

Since apparently using Micro QR codes has not become widespread enough (yet?) to merit adding support for reading them in any library I could find, I was looking for a workaround. In my search I came across one or two online QR readers that support decoding micro QR codes. Since I am just learning Playwright for Python, I thought, I'd give it a try.

The code below uses playwright to open an online QR code decoder website, click through the page to set the correct options, upload the image file and then read the result from the page.

I am aware that this is a completely convoluted way and noone would do this in production code, but it was fun and it does work :) Though it does not qualify as "simple" as the OP requested, I'm afraid.

from playwright import sync_playwright
import segno

segno.make_micro("1").save("1.png", scale=10)

with sync_playwright() as p:
   browser = p.firefox.launch(headless=False)
   page = browser.newPage()
   page.goto('https://www.datasymbol.com/barcode-reader-sdk/barcode-reader-sdk-for-windows/online-barcode-decoder.html')
   page.querySelector('select[name=\"sr\"]').selectOption([{'label': 'Text'}])
   page.querySelector('img[alt=\"QRCode Decoder Scanner Settings\"]').click()
   page.querySelector('input[name=\"qrmicro\"]').click()
   page.querySelector('input[id=\"fupload1\"]').setInputFiles('1.png')
   page.querySelector('input[type=\"button\"]').click()
   iframe = page.querySelector('iframe[name=\"f2\"]').contentFrame()
   result = iframe.querySelector('css=pre').innerHTML().rstrip()
   print(result)
   browser.close()

prints

1

Some notes:

  • if you do not want to see the page during execution, simply delete headless=False.
  • apparently, there is a pretty unpleasant limitation to using at least the service I chose: if the text you encode is longer than two characters, the website will change the first two characters to **, so if you encoded One Two Three you will retrieve **e Two Three. This is a limitation if you do not create the barcodes yourself. If you do, simply add ** at the beginning of your contents in the first place.
  • if you do want to use a remote service but don't want the complex way via the web interface, there are services that offer a direct API you can use e.g. with requests. The site I chose above apparently also offers something like that and there seems to be a free plan. But I never used it so I can't say anything about it.

Solution 2:

PyBoof just got updated and now supports scanning / reading Micro QR Codes and generating them too. See example code on Github for detecting and creating. Below is a copy of the code for scanning/detecting:

import numpy as np
import pyboof as pb

# Detects all the QR Codes in the image and prints their message and location
data_path = "../data/example/fiducial/microqr/image01.jpg"

detector = pb.FactoryFiducial(np.uint8).microqr()

image = pb.load_single_band(data_path, np.uint8)

detector.detect(image)

print("Detected a total of {} QR Codes".format(len(detector.detections)))

for qr in detector.detections:
    print("Message: " + qr.message)
    print("     at: " + str(qr.bounds))

PyBoof is a wrapper around BoofCV so you might want to check that out also.