Reputation: 6361
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:
I'm getting :
any idea?
Upvotes: 2
Views: 840
Reputation: 284612
You're having overflow problems when you're casting things back to uint8
s.
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