Search code examples
pythonpython-3.xtkinterpython-imaging-libraryyolo

AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'


I am working on Yolo3-4-PY to implement it with Tkinter.

I've looked everywhere but have not been 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'

Solution

  • 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.