Moj
Moj

Reputation: 6361

ImageTk.PhotoImage can't display image properly

I am trying convert a numpy array to PIL format and then display it as a label !I can do it for my original image but after I take the fft and and fftshift I can not display it properly.!

image1=Image.open('sam.jpg')
image1 = image1.resize((120, 120), Image.ANTIALIAS)
Labe(image=photo1).grid(row=0, column=7, columnspan=3, rowspan=2, padx=5, pady=5)
ipx1=np.array(image1)
(w,h)=ipx1.shape #120x20

now I do some stuff with my image:

img_fft=np.fft.fft2(image1)
img_shift=np.fft.fftshift(image1_fft)
img_plot1=np.log10(1+abs(img_shift))


foto=Image.fromarray((img_plot1*255.999).round().astype(np.uint8),mode='L')
photo=ImageTk.PhotoImage(foto)
Label(image=photo).grid(row=0, column=10, columnspan=4, rowspan=2, padx=5, pady=5)

but instead of: correct imag

I'm getting :

wrong image

any idea?

Upvotes: 2

Views: 840

Answers (1)

Joe Kington
Joe Kington

Reputation: 284612

You're having overflow problems when you're casting things back to uint8s.

You're converting with (img_plot1*255.999).round().astype(np.uint8), but this will overflow for values near or at 1. (anything greater than 0.998)

Assuming img_plot1 will always contain values between 0 and 1, I think you meant to just do either:

(img_plot1 * 255.99).astype(np.uint8)

or

(img_plot1 * 255).round().astype(np.uint8) 

The round call will round up or down, whereas a pure int cast is effectively a floor call.

However, just guessing from the "bands" in the output image, your input data is overflowing and "wrapping" multiple times. Therefore, your input data probably has a greater range than 0-1.

Therefore, if you don't want to worry about the exact range of values in img_plot1, you could just rescale it to 0-255 based on its range:

rescaled = 255 * (img_plot1 - img_plot1.min()) / img_plot1.ptp()
foto = Image.fromarray(rescaled.astype(np.uint8), mode='L')

You can also use np.digitize to rescale the array, but it winds up being less readable, i.m.o. Also have a look at np.clip if you want to clip values above and below a threshold (e.g. 0 and 255).

Upvotes: 2

Related Questions