How to find and read data matrix code using python
I am trying to read datamatrix barcodes on the bottom of microtubes. I tried libdmtx which has python bindings and works well enough when the matrix points are square, but much worse when they are round like here
Another complication is gloss, which in some cases reaches the area of ββthe code.
Barcodes are scanned in a rack on a flatbed scanner, so they are consistent in size and roughly centered. The orientation is random.
I came to the conclusion that I would need to find the codes and improve the image. I am using python and OpenCV 3.1. I've already tried threshold, outlines:
import matplotlib.pyplot as plt import numpy as np import cv2 well = plt.imread('/img/af59b9c68dbc59956e011f28e9879152.png') well = cv2.cvtColor(well, cv2.COLOR_BGRA2GRAY) plt.subplot(151); plt.imshow(well) x, thr = cv2.threshold(well, .4[enter image description here][2], 1, cv2.THRESH_BINARY) thr = np.uint8(thr) plt.subplot(152); plt.imshow(thr) dst, contours, hierarchy = cv2.findContours(thr.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) c = cv2.drawContours(np.zeros_like(thr), contours, -1, 255, 1) plt.subplot(153); plt.imshow(c) areas = map(lambda x: cv2.contourArea(cv2.convexHull(x)), contours) max_i = areas.index(max(areas)) d = cv2.drawContours(np.zeros_like(thr), contours, max_i, 255, 1) plt.subplot(154); plt.imshow(d) rect = cv2.minAreaRect(contours[max_i]) box = cv2.boxPoints(rect) box = np.int0(box) e = cv2.drawContours(np.zeros_like(thr),[box],0,255,1) plt.subplot(155); plt.imshow(e) plt.show()
source to share
It turns out that the Harris corner detector (B) finds round elements with the correct settings very well.
After the threshold (C), we detect the contours of the resulting regions. Select the largest path (D) and find the smallest bounding rectangle (E).
import matplotlib.pyplot as plt import numpy as np import cv2 well = plt.imread('https://i.stack.imgur.com/kqHkw.png') well = cv2.cvtColor(well, cv2.COLOR_BGRA2GRAY) plt.subplot(151); plt.title('A') plt.imshow(well) harris = cv2.cornerHarris(well,4, 1,0.00) plt.subplot(152); plt.title('B') plt.imshow(harris) x, thr = cv2.threshold(harris, 0.1 * harris.max(), 255, cv2.THRESH_BINARY) thr = thr.astype('uint8') plt.subplot(153); plt.title('C') plt.imshow(thr) dst, contours, hierarchy = cv2.findContours(thr.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) areas = map(lambda x: cv2.contourArea(cv2.convexHull(x)), contours) max_i = areas.index(max(areas)) d = cv2.drawContours(np.zeros_like(thr), contours, max_i, 255, 1) plt.subplot(154); plt.title('D') plt.imshow(d) rect =cv2.minAreaRect(contours[max_i]) box = cv2.boxPoints(rect) box = np.int0(box) e= cv2.drawContours(well,[box],0,1,1) plt.subplot(155); plt.title('E') plt.imshow(e) plt.show()
source to share