'How to improve pylibdmtx performance?

I am using pylibdmtx in Python 3.6 to detect barcode types (Datamatrix) which can't be detected by zbar. Unfortunately, documentation is sparse and the barcode detection is painfully slow, taking up to 30 seconds per image on a machine with relatively recent hardware. What are some ways I can speed up the detection time? My current code is as follows which gets me down to about 20 seconds but is still way too slow.

from PIL import Image
import cv2
from pylibdmtx.pylibdmtx import decode as dmtxdecode
image = cv2.imread(imagepath, cv2.IMREAD_UNCHANGED);
scale_percent = 50
width = int(image.shape[1] * scale_percent / 100)
height = int(image.shape[0] * scale_percent / 100)
dsize = (width, height)
# calculate the 50 percent of original dimensions
output = cv2.resize(image, dsize)
gray = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
pylibresult = dmtxdecode(thresh)


Solution 1:[1]

Speed is an issue, but with some compromises reasonable speeds can be achieved.

I picked a random image from internet with medium resolution. e.g. https://www.matthews.com.au/application/third_party/ckfinder/userfiles/images/printed-datamtrix.jpg

Here is the detected output (to know width and height): [Decoded(data=b'011234567890123110HJS6491715022821923Z845Y716W', rect=Rect(left=372, top=250, width=47, height=70))]

This pic without any arguments takes 4.18 sec to run!

Adding arg:

  • max_count=1 -> 0.75 sec (5,5x improvement!)

Now all the following test have max_count=1

  • threshold=50 -> 0.26 sec (2,9x further improvement)
  • min_edge=20 -> 0.71 sec (1,05x)
  • max_edge=60 -> 0.22 sec (3,4x)
  • shape=DmtxSymbolSize.DmtxSymbol24x24 -> na - some further improvement possible.

Combined: max_count=1, threshold=50, min_edge=20, max_edge=60 -> 0.17 sec (4,4x)

Please note: this just gives an indication of the effect of parameters. Actual time depends on image content, resolution, position and size of the first tag etc. Durations where averaged over 2 tests (since values matched really well).

CPU: 2.6 GHz i5-4278U, MBP late 2014 libdmtx: 0.7.5 pylibdmtx: 0.1.9

from pylibdmtx.pylibdmtx import decode
import cv2, time

path = 'printed-datamtrix.jpg'
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

for _ in range(2):
    start = time.time()
    res = decode(gray, max_count=1, threshold=50, min_edge=20, max_edge=60)
    print("elapsed: ", time.time() - start)

Solution 2:[2]

Shrink and Threshold combined will get it down to 4 sec

import cv2
from pylibdmtx.pylibdmtx import decode

image = cv2.imread('img.png')
decode(image, shrink=3, threshold=6)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lev5
Solution 2 S.B