AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Question:
I am working on Yolo3-4-PY to implement it with tkinter.
I’ve looked up everywhere but not able to resolve the issue.
When I run the program the canvas is displayed but when I click on Start Video(btton) I get the following error:
Loading weights from weights/yolov3.weights…Done!
/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py:119: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
if mode not in [“1”, “L”, “RGB”, “RGBA”]:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "webcam_demo.py", line 13, in start_video
show_frame()
File "webcam_demo.py", line 39, in show_frame
imgtk = ImageTk.PhotoImage(image=cv2image)
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py", line 120, in
__init__
mode = Image.getmodebase(mode)
File "/usr/local/lib/python3.5/dist-packages/PIL/Image.py", line 313, in
getmodebase
return ImageMode.getmode(mode).basemode
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageMode.py", line 55, in
getmode
return _modes[mode]
TypeError: unhashable type: 'numpy.ndarray'
Exception ignored in: <bound method PhotoImage.__del__ of
<PIL.ImageTk.PhotoImage object at 0x7f4b73f455c0>>
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py", line 130, in
__del__ name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Answers:
Issue
In the line imgtk = ImageTk.PhotoImage(image=cv2image)
, you are passing a numpy array (cv2image) as input to ImageTk.PhotoImage. But the source code of PIL.ImageTk mentions that it requires a PIL image.
This is what source code of PIL.ImageTk mentions for init() of PhotoImage.
class PhotoImage(object):
.....
:param image: Either a PIL image, or a mode string. If a mode string is
used, a size must also be given.
Solution
So basically, you will have to convert the numpy array to a PIL Image and then pass it to ImageTk.PhotoImage().
So, can you replace the line imgtk = ImageTk.PhotoImage(image=cv2image)
with imgtk = ImageTk.PhotoImage(image=PIL.Image.fromarray(cv2image))
?
This would convert the numpy array to a PIL Image and it would be passed into the method.
References
I extracted the code for converting a numpy array to PIL Image from this source.
in my case , correct with just simply add this line
root = tkinter.Tk()
complete code :
root = tkinter.Tk()
image = PIL.Image.open(r"C:UsersHamidDesktopasdasd2.jpeg")
img = ImageTk.PhotoImage(image)
l = Label(image=img)
l.pack()
when you place the image variable in the label , you must initiate the image variable to "image".
Eg: (CORRECT APPROACH)
photo = PhotoImage(file = "C://Users//Carl//Downloads//download.png")
label1 = Label(image = photo)
label1.pack()
Eg : (WRONG APPROACH)
photo = PhotoImage(file = "C://Users//Carl//Downloads//download.png")
label1 = Label(photo)
label1.pack()
Interesting…. there’s apparently a nasty side-effect in Tkinter which can cause this.
Note (from hamidjahandideh’s answer ) that it matters that you create your root window BEFORE cresting the ImageTk.
ie. this fails with AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
im_numpy = cv2.imread(ResourcePhotos.BLUE_PERSON_TRAIL_PHOTO)[:, :, ::-1].copy() # Load BGR Image
im_pil = Image.fromarray(im_numpy)
imagetk = ImageTk.PhotoImage(im_pil)
window = tk.Tk() # This line must come BEFORE crearting ImageTk
tk.Label(window, image=imagetk).pack()
window.mainloop()
But this works:
im_numpy = cv2.imread(ResourcePhotos.BLUE_PERSON_TRAIL_PHOTO)[:, :, ::-1].copy() # Load BGR Image
im_pil = Image.fromarray(im_numpy)
window = tk.Tk() # This line must come BEFORE creating ImageTk
imagetk = ImageTk.PhotoImage(im_pil)
tk.Label(window, image=imagetk).pack()
window.mainloop()
I am working on Yolo3-4-PY to implement it with tkinter.
I’ve looked up everywhere but not able to resolve the issue.
When I run the program the canvas is displayed but when I click on Start Video(btton) I get the following error:
Loading weights from weights/yolov3.weights…Done!
/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py:119: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
if mode not in [“1”, “L”, “RGB”, “RGBA”]:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "webcam_demo.py", line 13, in start_video
show_frame()
File "webcam_demo.py", line 39, in show_frame
imgtk = ImageTk.PhotoImage(image=cv2image)
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py", line 120, in
__init__
mode = Image.getmodebase(mode)
File "/usr/local/lib/python3.5/dist-packages/PIL/Image.py", line 313, in
getmodebase
return ImageMode.getmode(mode).basemode
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageMode.py", line 55, in
getmode
return _modes[mode]
TypeError: unhashable type: 'numpy.ndarray'
Exception ignored in: <bound method PhotoImage.__del__ of
<PIL.ImageTk.PhotoImage object at 0x7f4b73f455c0>>
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/PIL/ImageTk.py", line 130, in
__del__ name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Issue
In the line imgtk = ImageTk.PhotoImage(image=cv2image)
, you are passing a numpy array (cv2image) as input to ImageTk.PhotoImage. But the source code of PIL.ImageTk mentions that it requires a PIL image.
This is what source code of PIL.ImageTk mentions for init() of PhotoImage.
class PhotoImage(object):
.....
:param image: Either a PIL image, or a mode string. If a mode string is
used, a size must also be given.
Solution
So basically, you will have to convert the numpy array to a PIL Image and then pass it to ImageTk.PhotoImage().
So, can you replace the line imgtk = ImageTk.PhotoImage(image=cv2image)
with imgtk = ImageTk.PhotoImage(image=PIL.Image.fromarray(cv2image))
?
This would convert the numpy array to a PIL Image and it would be passed into the method.
References
I extracted the code for converting a numpy array to PIL Image from this source.
in my case , correct with just simply add this line
root = tkinter.Tk()
complete code :
root = tkinter.Tk()
image = PIL.Image.open(r"C:UsersHamidDesktopasdasd2.jpeg")
img = ImageTk.PhotoImage(image)
l = Label(image=img)
l.pack()
when you place the image variable in the label , you must initiate the image variable to "image".
Eg: (CORRECT APPROACH)
photo = PhotoImage(file = "C://Users//Carl//Downloads//download.png")
label1 = Label(image = photo)
label1.pack()
Eg : (WRONG APPROACH)
photo = PhotoImage(file = "C://Users//Carl//Downloads//download.png")
label1 = Label(photo)
label1.pack()
Interesting…. there’s apparently a nasty side-effect in Tkinter which can cause this.
Note (from hamidjahandideh’s answer ) that it matters that you create your root window BEFORE cresting the ImageTk.
ie. this fails with AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
im_numpy = cv2.imread(ResourcePhotos.BLUE_PERSON_TRAIL_PHOTO)[:, :, ::-1].copy() # Load BGR Image
im_pil = Image.fromarray(im_numpy)
imagetk = ImageTk.PhotoImage(im_pil)
window = tk.Tk() # This line must come BEFORE crearting ImageTk
tk.Label(window, image=imagetk).pack()
window.mainloop()
But this works:
im_numpy = cv2.imread(ResourcePhotos.BLUE_PERSON_TRAIL_PHOTO)[:, :, ::-1].copy() # Load BGR Image
im_pil = Image.fromarray(im_numpy)
window = tk.Tk() # This line must come BEFORE creating ImageTk
imagetk = ImageTk.PhotoImage(im_pil)
tk.Label(window, image=imagetk).pack()
window.mainloop()