png file shows bluish image when using plt.imshow() - numpy

I'm trying to plot a png file using matplotlib.pyplot.imshow() but it's showing a bluish image(see below). It works for jpeg file but not for png.
This is the code:
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
im = Image.open('apple_logo.png')
im.save('test.png') #test.png is same as original
data = np.array(im)
print(data)
plt.imshow(data) #shows a bluish image of the logo
The image i'm using:
bluish image:
Python 3.8.2
matplotlib 3.3.0
Pillow 7.2.0
numpy 1.19.0
OS: Windows 10

The original PNG image is an indexed PNG file. That is, it has a palette (i.e. a lookup table for the colors), and the array of data that makes up the image is an array of indices into the lookup table. When you convert im to a numpy array with data = np.array(im), data is the array of indices into the palette, instead of the array of actual colors.
Use the convert() method before passing the image through numpy.array:
data = np.array(im.convert())

Related

Convert np.array of PIL image to binary

Im trying to convert the numpy array of the PIL image I got to a binary one but anything I have tried doesn't work.
this is what I got so far:
from PIL import Image
import numpy as np
pixels=np.array(Image.open("covid_encrypted_new.png").getdata())
def to_bin(pixels):
return [format(i,"08b") for i in pixels]
also when I tried to iterate over the array and change each value to type bin it also didnt go well for me.
What else can I try?
thanks
This could be what your looking for
Ori here: How to read the file and convert it to a binary image in Python
# Read Image
img= Image.open(file_path)
# Convert Image to Numpy as array
img = np.array(img)
# Put threshold to make it binary
binarr = np.where(img>128, 255, 0)
# Covert numpy array back to image
binimg = Image.fromarray(binarr)
You could even use opencv to convert
img = np.array(Image.open(file_path))
_, bin_img = cv2. threshold(img,127,255,cv2.THRESH_BINARY)

Spectral Python imshow displaying scrambled image

I am learning Spectral Python and using their own documentation and sample image files to display a multispectral image as RGB. However, for some reason, my image appears scrambled up. I have tested the image file by opening it in MultiSpec and it appears as it should, so I do not think the file is damaged. My code is as follows:
import spectral as s
import matplotlib as mpl
path = '/content/92AV3C.lan'
img = s.open_image(path)
print(img)
#Load and display hyperspectral image
arr = img.load()
view = s.imshow(arr, (29, 19, 9))
print(view)
#Load and display Ground truth image
gt = s.open_image('92AV3GT.GIS').read_band(0)
view = s.imshow(classes=gt)
Output is as follows:
I suggest that you try the following command instead of view=imshow(img, (RGB))`. SpectralPython has the smarts, once you identify the image type, i.e., *.lan to display the image in the correct format.

How to save an image that has been visualized/generated by a Keras model?

I am using detecto model to visualize an image. So basically I am passing an image to this model and it will draw a boundary line accross the object and dislay the visualized image.
from keras.preprocessing.image import load_img
from keras.preprocessing.image import save_img
from keras.preprocessing.image import img_to_array
from detecto import core, utils, visualize
image = utils.read_image('retina_model/4.jpg')
model = core.Model()
labels, boxes, scores = model.predict_top(image)
img=visualize.show_labeled_image(image, boxes,)
Now, I am trying to convert this visualized image into Numpy array. I am using the below line for converting the image into numpy array :
img_array = img_to_array(img)
It is giving the errror :
Unsupported Image Shape
All I want is to display the visualized image which is the output of this model to my website. The plan is to convert the image into numpy array and then save the image by code using the below line :
save_img('image1.jpg', img_array)
So I was planning to download this visualized image (output of this model) so that I can display the downloaded image to my website. If there is some other way to do achieve this then please let me know.
Detecto's documentation says the utils.read_image() is already returning a NumPy array.
But you are passing the return of visualize.show_labeled_image() to Keras' img_to_array(img)
Looking at the Detecto source code of visualize.show_labeled_image(), it has no return type, so it is returning None by default. So I think your problem is you are not passing a valid image to img_to_array(img), but None.
I don't think the call to img_to_array(img) is needed, because you already have the image as a NumPy array. But note that according to Detecto's documentation, utils.read_image() is "Equivalent to using OpenCV’s cv2.imread function and converting from BGR to RGB format" . Make sure that's what you want.
you can visit the official github repo of detecto/visualize.pyto find out the show_labeled_image() function it uses matplotlib to plot the image with bounding boxes you can modify that code in your file to save the plot using plt.save_fig()

Matplotlib: Get Rid of White Border

I want to get rid of the white border when I save my image to a png in python.
I tried plt.box(on=None), plt.axis('off'). I tried setting the figure's 'frameon' parameter to false.
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
figure(num=None, figsize=(7.965,7.965), dpi=80,facecolor='none',clear=True)
plt.box(on=None)
plt.axis('off')
plt.imshow(Data, cmap='Greys_r', norm=Norm,origin='lower',aspect='auto',interpolation='nearest')
plt.savefig(locationFITSfolder+fitsFile[:-5],transparent=False,bbox=False)
I want there to be no white border to my image. Transparent.
If you change the parameters to the savefig function, you will get the desired output.
Specifically, you must use transparent=True. Note that bbox=False and frameon=False are optional, and only change the width of transparent space around your image.
Adapting from your sample code:
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
#create sample data
import numpy as np
Data = np.random.random([4,4])
figure(num=None, figsize=(7.965,7.965), dpi=80,facecolor='none',clear=True)
plt.box(on=None)
plt.axis('off')
plt.imshow(Data, cmap='Greys_r',origin='lower',aspect='auto',interpolation='nearest')
plt.savefig(locationFITSfolder+fitsFile[:-5],transparent=True)
(sidenote -- you may wish to use os.path.join, .split, and .splitext for file I/O, instead of slicing string names)
This yields the expected image output: (note that the image has transparent borders when you open it in a new tab or download it).

Slicing the channels of image and storing the channels into numpy array(same size as image). Plotting the numpy array not giving the original image

I separated the 3 channels of an colour image. I created a new NumPy array of the same size as the image, and stored the 3 channels of the image into 3 slices of the 3D NumPy array. After plotting the NumPy array, the plotted image is not same as original image. Why is this happening?
Both img and new_img array have same elements, but image is different.
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import numpy as np
img=mpimg.imread('/storage/emulated/0/1sumint/kali5.jpg')
new_img=np.empty(img.shape)
new_img[:,:,0]=img[:,:,0]
new_img[:,:,1]=img[:,:,1]
new_img[:,:,2]=img[:,:,2]
plt.imshow(new_img)
plt.show()
Expect the same image as original image.
The problem is that your new image will be created with the default data type of float64 on this line:
new_img=np.empty(img.shape)
unless you specify a different dtype.
You can either (best) copy the original image's dtype like this:
new_img = np.empty(im.shape, dtype=img.dtype)
or use something like this:
new_img = np.zeros_like(im)
or (worst) specify one you happen to know matches your data, like this,
new_img = np.empty(im.shape, dtype=np.uint8)
I presume you have some reason for copying one channel at a time, but if not, you can avoid all the foregoing issues and just do:
new_img = np.copy(img)