TypeError: 'bytes' object cannot be interpreted as an integer
Question:
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:UsersarccovenvScriptspython.exe D:PythonpythonProjecttest.py
Traceback (most recent call last):
File "D:PythonpythonProjecttest.py", line 45, in <module>
img = decode(img)
^^^^^^^^^^^
File "D:PythonpythonProjecttest.py", line 19, in decode
ser.write (a)
File "C:UsersarccovenvLibsite-packagesserialserialwin32.py", line 310, in write
data = to_bytes(data)
^^^^^^^^^^^^^^
File "C:UsersarccovenvLibsite-packagesserialserialutil.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
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)
Answers:
Debug and consult the docs
Let’s do 3 things to solve your issue:
- Clarify the output expected from pyzbar’s docs of the
decode
function.
- Debug the existing code by adding print statements for output and types
- Clarify the input expected by pyserial’s docs of the
write
function.
Expected output from 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?.
Debugging details
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',
Expected input for pyserial’s write(data)
The method write(data)
accepts
Write the bytes data to the port. This should be of type bytes
(or compatible such as bytearray
or memoryview
). Unicode strings must be encoded (e.g. 'hello'.encode('utf-8')
.
Changed in version 2.5: Accepts instances of bytes
and bytearray
when available (Python 2.6 and newer) and str
otherwise.
So following example should work, since it passes bytes to the function:
ser.write(b'bytes')
Issues
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 bytes
bytes([obj.data])
raises:
TypeError: ‘bytes’ object cannot be interpreted as an integer
- in your first attempt
bytes(a)
is equivalent with bytes( (bytes([obj.data])) )
which seems a bit obsolete
- in your second attempt of passing
a.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
Solution
for obj in pyzbar.decode(image):
ser.write(obj.data) # assume obj.data is of type bytes
See also
Related questions:
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:UsersarccovenvScriptspython.exe D:PythonpythonProjecttest.py
Traceback (most recent call last):
File "D:PythonpythonProjecttest.py", line 45, in <module>
img = decode(img)
^^^^^^^^^^^
File "D:PythonpythonProjecttest.py", line 19, in decode
ser.write (a)
File "C:UsersarccovenvLibsite-packagesserialserialwin32.py", line 310, in write
data = to_bytes(data)
^^^^^^^^^^^^^^
File "C:UsersarccovenvLibsite-packagesserialserialutil.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
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)
Debug and consult the docs
Let’s do 3 things to solve your issue:
- Clarify the output expected from pyzbar’s docs of the
decode
function. - Debug the existing code by adding print statements for output and types
- Clarify the input expected by pyserial’s docs of the
write
function.
Expected output from 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?.
Debugging details
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',
Expected input for pyserial’s 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')
Issues
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 alist
of bytesbytes([obj.data])
raises:
TypeError: ‘bytes’ object cannot be interpreted as an integer
- in your first attempt
bytes(a)
is equivalent withbytes( (bytes([obj.data])) )
which seems a bit obsolete - in your second attempt of passing
a.encode()
as argument to thewrite
function you got an error. The encode function only works on string. Buta
is a list, so the statementa.encode()
raises thisAttributeError
.
In Python’s interactive REPL you can reproduce each error, try out:
bytes([bytes()])
for the firstTypeError
list().encode()
for the secondAttributeError
Solution
for obj in pyzbar.decode(image):
ser.write(obj.data) # assume obj.data is of type bytes
See also
Related questions: