Reputation: 21
I use OpenCV to read a barcode and send it to an Arduino via serial communication using package pyserial
.
The goal is to make a robotic arm move the object (much like in amazon warehouses).
When sending the bytes it shows this error:
C:\Users\arcco\venv\Scripts\python.exe D:\Python\pythonProject\test.py
Traceback (most recent call last):
File "D:\Python\pythonProject\test.py", line 45, in <module>
img = decode(img)
^^^^^^^^^^^
File "D:\Python\pythonProject\test.py", line 19, in decode
ser.write (a)
File "C:\Users\arcco\venv\Lib\site-packages\serial\serialwin32.py", line 310, in write
data = to_bytes(data)
^^^^^^^^^^^^^^
File "C:\Users\arcco\venv\Lib\site-packages\serial\serialutil.py", line 68, in to_bytes
return bytes(bytearray(seq))
^^^^^^^^^^^^^^
TypeError: 'bytes' object cannot be interpreted as an integer
detected barcode: Decoded(data=b'43770929851162', type='I25', rect=Rect(left=62, top=0, width=694, height=180), polygon=[Point(x=62, y=1), Point(x=62, y=179), Point(x=756, y=180), Point(x=756, y=0)], quality=181, orientation='UP')
Type: I25
Data: b'43770929851162'
Process finished with exit code 1
Code where I tried to send the bytes array to serial.
from pyzbar import pyzbar
import cv2
import serial
ser = serial.Serial("COM3", 9600)
def decode(image):
# decodes all barcodes from an image
decoded_objects = pyzbar.decode(image)
for obj in decoded_objects:
# draw the barcode
print("detected barcode:", obj)
image = draw_barcode(obj, image)
# print barcode type & data
print("Type:", obj.type)
print("Data:", obj.data)
print()
a = (bytes([obj.data]))
ser.write(bytes(a))
return image
def draw_barcode(decoded, image):
# n_points = len(decoded.polygon)
# for i in range(n_points):
# image = cv2.line(image, decoded.polygon[i], decoded.polygon[(i+1) % n_points], color=(0, 255, 0), thickness=5)
# uncomment above and comment below if you want to draw a polygon and not a rectangle
image = cv2.rectangle(image, (decoded.rect.left, decoded.rect.top),
(decoded.rect.left + decoded.rect.width, decoded.rect.top + decoded.rect.height),
color=(0, 255, 0),
thickness=5)
return image
if __name__ == "__main__":
from glob import glob
barcodes = glob("barcode*.png")
for barcode_file in barcodes:
# load the image to opencv
img = cv2.imread(barcode_file)
# decode detected barcodes & get the image
# that is drawn
img = decode(img)
# show the image
cv2.imshow("img", img)
cv2.waitKey(0)
Upvotes: -1
Views: 14667
Reputation: 9377
Let's do 3 things to solve your issue:
decode
function.write
function.pyzbar.decode(image)
pyzbar.decode(image)
returns an array of Decoded
named-tuples. Each tuple has an attribute named data
which contains bytes like b'some bytes'
. An example of the returned objects can be seen in the project's GitHub README in section Example Usage.
See also What does the 'b' character do in front of a string literal?.
So in your code the following debug printing output of obj.data
should look similar to b'...'
(bytes) and type(obj.data)
should be printed as <class 'bytes'>
:
# debug output
print(obj.data)
print(type(obj.data))
For the obj
of type Decoded
your given output shows the attribute data
to have type bytes
(denoted by prefix "b"). So apparently the decoded data contains as sequence of digits, a barcode of type I25
for Interleaved 2 of 5:
Decoded(data=b'43770929851162', type='I25',
write(data)
The method write(data)
accepts
Write the bytes data to the port. This should be of type
bytes
(or compatible such asbytearray
ormemoryview
). Unicode strings must be encoded (e.g.'hello'.encode('utf-8')
.Changed in version 2.5: Accepts instances of
bytes
andbytearray
when available (Python 2.6 and newer) andstr
otherwise.
So following example should work, since it passes bytes to the function:
ser.write(b'bytes')
Let's analyze your faulty lines:
a = (bytes([obj.data])) # obsolete conversion
# your first attempt
ser.write(bytes(a)) # raises TypeError
# also your second attempt
ser.write(a.encode()) # raises AttributeError
Given obj.data
is of needed type bytes
already, then:
[obj.data]
is a list
of bytesbytes([obj.data])
raises:
TypeError: 'bytes' object cannot be interpreted as an integer
bytes(a)
is equivalent with bytes( (bytes([obj.data])) )
which seems a bit obsoletea.encode()
as argument to the write
function you got an error. The encode function only works on string. But a
is a list, so the statement a.encode()
raises this AttributeError
.In Python's interactive REPL you can reproduce each error, try out:
bytes([bytes()])
for the first TypeError
list().encode()
for the second AttributeError
for obj in pyzbar.decode(image):
ser.write(obj.data) # assume obj.data is of type bytes
Related questions:
Upvotes: 1