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

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'

in my case , correct with just simply add this line
root = tkinter.Tk()
complete code :
root = tkinter.Tk()
image = PIL.Image.open(r"C:\Users\Hamid\Desktop\asdasd\2.jpeg")
img = ImageTk.PhotoImage(image)
l = Label(image=img)
l.pack()

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.

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()

Related

TypeError: unhashable type: 'numpy.ndarray' Python3.9 image classification using tensorflow and keras

I try this sample code for image classification
def show_classify_button(file_path):
classify_btn = Button(top, text="Classify Image", command=lambda: classify(file_path), padx=10, pady=5)
classify_btn.configure(background="#364156", foreground="white", font=('arial',10,'bold'))
classify_btn.place(relx=0.79,rely=0.46)
def classify(file_path):
image = Image.open(file_path)
image = image.resize((32,32))
image = numpy.expand_dims(image, axis=0)
image = numpy.array(image)
pred = model.predict([image])[0]
sign = classes[pred]
print(sign)
label.configure(foreground='#011638')
the terminal pop this
Traceback (most recent call last):
line 39, in <lambda>
classify_btn = Button(top, text="Classify Image", command=lambda: classify(file_path), padx=10, pady=5)
line 49, in classify
sign = classes[pred]
TypeError: unhashable type: 'numpy.ndarray'
I try to check the data from the pred with output
[30990.06 46435.57 17636.973 16334.658 15860.342 16765.371 26879.748
14579.97 41989.523 34359.215]
im not sure why because the data is from set of an array
im new with this and im using python3.9 can someone help me
You're trying to access classes variable on line 49
sign = classes[pred]
classes is of type numpy.ndarray.
So you're trying to access an array at index pred but because pred is not an number it's raising a unhashable type: 'numpy.ndarray' error.
You're treating classes like a dictionary by accessing it's values with a key and not with an index.

Random image looping in tkinter

I'm trying to loop random images from a folder. So far, I can loop the images but everytime I try to use random.choice, I'm getting an error. Below is my code without random imported
import tkinter as tk
import glob
root = tk.Tk()
from PIL import ImageTk, Image
root.geometry('600x600')
pics = glob.glob("./imgs/*.png")
photos = [random.choice(tk.PhotoImage(file=x)) for x in pics]
label = tk.Label(root)
label.photos = photos
label.counter = 0
def changeimage():
label['image'] = label.photos[label.counter%len(label.photos)]
label.after(8000, changeimage)
label.counter += 1
label.pack(padx=10, pady=10)
changeimage()
root.mainloop()
Error
Traceback (most recent call last):
File "/Users/ad/Documents/Python/Project_tkinter/test1.py", line 148, in <module>
photos = [random.choice(tk.PhotoImage(file=x)) for x in pics]
File "/Users/ad/Documents/Python/Project_tkinter/test1.py", line 148, in <listcomp>
photos = [random.choice(tk.PhotoImage(file=x)) for x in pics]
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/random.py", line 288, in choice
i = self._randbelow(len(seq))
TypeError: object of type 'PhotoImage' has no len()
You have to first create list of photos and later choose single photo
list_of_photos = [tk.PhotoImage(file=x) for x in pics]
single_photo = random.choice(list_of_photos)
but if you want to loop this list then you rather need random.shuffle() to change order on the list to have files in random order.
list_of_photos = [tk.PhotoImage(file=x) for x in pics]
random.shuffle(list_of_photos)
random.shuffle() changes original list and it doesn't return new list.

Error When I Merge .tif into RGB band by python's PIL

from PIL import Image
band2 = Image.open('band2.tif')
band3 = Image.open('band3.tif')
band4 = Image.open('band4.tif')
img = Image.merge("RGB",(band4,band3,band2))
the band2.tif,band3.tif,band4.tif are downloaded in USGS(https://earthexplorer.usgs.gov/).
they may have some differents compared to the normal .TIF
the error information is
/usr/bin/python3.5 /home/lixingang/workspace/20170405/main.py
Traceback (most recent call last):
File "/home/lixingang/workspace/20170405/main.py", line 5, in <module>
img = Image.merge("RGB",(band4,band3,band2))
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2388, in merge
raise ValueError("mode mismatch")
ValueError: mode mismatch
Process finished with exit code 1
You need to convert each channel into a luminosity channel. So instead of this:
band2 = Image.open('band2.tif')
You need do this:
band2 = Image.open('band2.tif').convert('L')
The same as other channels, for merge the order should also be considered.

How to reduce gif quality using wand?

I have the following code
from wand.image import Image
def saveSizes(f, filename):
scaled_width = 400
scaled_hight = 400
with Image() as finalImage:
with Image(filename=f) as img:
for frame in img.sequence:
#frame.transform(resize="%dx%d" % (scaled_width, scaled_hight))
frame.compression_quality = 75
finalImage.sequence.append(frame)
filename += '.gif'
finalImage.save(filename = filename)
saveSizes('source_file.gif', 'dest_file')
But the size of 'source_file.gif' is same as that of 'dest_file.gif'. Why is the "compression_quality" attribute not working?
Is there a better way to reduce the size of gif using wand or some other python lib.?
Also I am getting the following log in the console for every frame in the gif.
Exception ignored in: <bound method Resource.__del__ of <wand.sequence.SingleImage: 901eb12 (200x150)>>
Traceback (most recent call last):
File "/usr/local/lib/python3.5/site-packages/wand/resource.py", line 232, in __del__
self.destroy()
File "/usr/local/lib/python3.5/site-packages/wand/sequence.py", line 331, in destroy
self.container.sequence[self.index] = self
File "/usr/local/lib/python3.5/site-packages/wand/sequence.py", line 304, in index
assert image
AssertionError:
compression_quality works fine with the source (whole file).
my working example with pdfs:
def ConvertFewPagePdfToPngs(pdf):
with wand.image.Image(filename = pdf, resolution = 200) as source:
source.compression_quality = 99
imagess = source.sequence
for i in range(len(imagess)):
imagess[i].format = 'png'
destFileName = r'path' # depends on i
wand.image.Image(imagess[i]).save(filename=destFileName)
When i tried apply compression_quality to one page i got same error as you show

Python tkinter ttk.Notebook widget error

I have a problem with the Notebook widget with python 3.3.2
This is the code:
gui=Tk()
gui.title("Test")
gui.geometry()
n = ttk.Notebook(gui).grid()
f1 = ttk.Frame(n)
f2 = ttk.Frame(n)
n.add(f1, text='One')
n.add(f2, text='Two')
gui.resizable(width=TRUE, height=TRUE)
mainloop()
and this is the error:
Traceback (most recent call last):
File "C:\Users\SergiX\Desktop\SergiX44's ModTool con sorgente 3.3\SergiX44's ModTool 1.6.4.py", line 179, in <module>
n.add(f1, text='One')
AttributeError: 'NoneType' object has no attribute 'add'
I don't know the reason of the error
thanks
The problem is that you're assigning the result of the grid function to n, rather than the Notebook widget itself. The grid function always returns None, so n has a value of None, thus the error.
To fix this, try replacing this line
n = ttk.Notebook(gui).grid()
with these lines
n = ttk.Notebook(gui)
n.grid()

Categories

Resources