BUG: Rect object returned by `decode` can be trivially wrong
See original GitHub issueThe rectangle object returned by the decode
function is (completely) wrong whenever the found DataMatrix code is rotated. The problem is that the returned rectangle is always supposed to be upright when, in fact, libdtmx supports also rotated codes.
Examples with one upright and one rotated DataMatrix code:
- direct call of
dmtxread
on the command line
(base) ➜ ~ dmtxread -n -v -N 1 12345_garbage.png
--------------------------------------------------
Matrix Size: 10 x 10
Data Codewords: 3 (capacity 3)
Error Codewords: 5
Data Regions: 1 x 1
Interleaved Blocks: 1
Rotation Angle: 0
Corner 0: (1152.0, 1287.0)
Corner 1: (1201.0, 1287.0)
Corner 2: (1200.1, 1238.0)
Corner 3: (1152.0, 1238.0)
--------------------------------------------------
12345
(base) ➜ ~ dmtxread -n -v -N 1 12345_garbage_rotated.png
--------------------------------------------------
Matrix Size: 10 x 10
Data Codewords: 3 (capacity 3)
Error Codewords: 5
Data Regions: 1 x 1
Interleaved Blocks: 1
Rotation Angle: 319
Corner 0: (1191.0, 1292.9)
Corner 1: (1228.1, 1325.2)
Corner 2: (1260.5, 1287.9)
Corner 3: (1223.4, 1255.6)
--------------------------------------------------
12345
- using
pylibdtmx
(libdmtx) ➜ ~ ipython
Python 3.7.5 (default, Oct 25 2019, 15:51:11)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.9.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from pylibdmtx.pylibdmtx import decode
In [2]: from PIL import Image
In [3]: decode(Image.open("/home/gri/12345_garbage.png"), max_count=1)
Out[3]: [Decoded(data=b'12345', rect=Rect(left=1152, top=2220, width=48, height=49))]
In [4]: decode(Image.open("/home/gri/12345_garbage_rotated.png"), max_count=1)
Out[4]: [Decoded(data=b'12345', rect=Rect(left=1191, top=2214, width=70, height=5))]
(Note how also width
and height
changed to totally incorrect values.)
The obvious solution would be to not return a tuple of left
, top
, width
, and height
coordinates, since they apply only to upright rectangles, but to return the coordinates of the four corners—as is done by the command line program.
So in these lines of the code all four points should be captured instead of only two ones.
Of course, such a change would break the interface as it is now. If you insist on returning an upright rectangle, it should at least be the upright bounding box of the DataMatrix code crop. But I would much prefer if the python version would just return the four corner points as the command line version does.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:14
Top GitHub Comments
yes you can do by easily adding two more vectors e.g p00 = DmtxVector2() p11 = DmtxVector2(1.0, 1.0) p10 = DmtxVector2(1.0, 0.0) p01 = DmtxVector2(0.0, 1.0) dmtxMatrix3VMultiplyBy(p00, region.contents.fit2raw) dmtxMatrix3VMultiplyBy(p11, region.contents.fit2raw) dmtxMatrix3VMultiplyBy(p01, region.contents.fit2raw) dmtxMatrix3VMultiplyBy(p10, region.contents.fit2raw) x00 = int((shrink * p00.X) + 0.5) y00 = int((shrink * p00.Y) + 0.5) x11 = int((shrink * p11.X) + 0.5) y11 = int((shrink * p11.Y) + 0.5) x10 = int((shrink * p10.X) + 0.5) y10 = int((shrink * p10.Y) + 0.5) x01 = int((shrink * p01.X) + 0.5) y01 = int((shrink * p01.Y) + 0.5) return Decoded( string_at(msg.contents.output), #Rect2 = namedtuple(‘Rect’, ‘x00 y00 x01 y01 x10 y10 x11 y11’) Rect2(x00,y00,x01,y01,x10,y10,x11,y11)
I did its in my lib and it works well
@GenericArt Not sure what @Gennadynemchin 's actual issue was, but I found that the when using @gauti1311 's solution to return 4 corners from the
_decode_region
, the y coordinate frame is flipped relative to the coordinate frame used by openCV images. You can simply subtract the input image’s height from the rectangle’s Y coordinates to get the proper pixel location.