Can't plot image with matplotlib after PIL convert('L') - python

I tried to convert RGB image into gray image and plot them. But I can't plot the gray image after PIL convert('L'). the following error was reported in the Spyder console (Python3.6). However, the original image can be plotted if i don't use the convert('L').
File "d:\ProgramData\Anaconda3\lib\site-packages\matplotlib\image.py", line 430, in _make_image
if A.mask.shape == A.shape:
AttributeError: 'numpy.ndarray' object has no attribute 'mask'
see my python code in below:
from PIL import Image, ImageFilter
import tensorflow as tf
import matplotlib.pyplot as plt
file_name='images\\2.4.1.png'
im0 = Image.open(file_name)
plt.imshow(im0)
plt.show()
im = im0.convert('L')
plt.imshow(im, cmap='gray')
plt.show() # Not working here

Trying using LA instead of just L as follows:
from PIL import Image, ImageFilter
import matplotlib.pyplot as plt
file_name = r'images\2.4.1.png'
im0 = Image.open(file_name).convert('LA')
plt.imshow(im0, cmap='gray')
plt.show()
The parameter specifies the conversion mode, in your case the PNG file probably has an alpha channel, so the A is needed.
See also: Pillow modes

Related

Python window-objects run order

To understand the Pyton Interpreter,
MY QUESTION :
If i select the first 9 line and RUN Selected, the plt codes work…
But If i RUN all the codes, plts codes doesnt work, jump to second img.show() section…
WHY?
and
How all codes work sequential…
CODE :
from PIL import Image
import numpy as np
import matplotlib.image as gg
import matplotlib.pyplot as plt
img2 = gg.imread("C:/Users/John/Desktop/BOUTTEQA/data/1.jpg")
# print(type(img2))
# print(img2.shape)
plt.imshow(img2)
plt.colorbar()
img = Image.open("C:/Users/John/Desktop/BOUTTEQA/data/1.jpg")
print(type(img))
img.show()
print(img.format)
img1 = np.asarray(img)

Why plt.imshow() isn't working in matplotlib

I'm trying to run a simple code that takes a traffic lights image & displays it as grayscale --> 'Original' and then takes the same image and displays only the parts of it which correspond to the upper and lower thresholds I pre-defined --> 'bright'. However, the following code when I run it, displays nothing.
when I change plt.imshow() to cv2.imshow() it does, so I'm confused as to why this happens. Both libraries are installed correctly. I even tried adding plt.show() at the end of the code, but still no output.
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_lights.jpeg')
plt.imshow(original,cmap='gray')
lower=150
upper = 254
bright = cv2.inRange(original,lower,upper)
plt.imshow(bright,cmap='gray')
I think you need to specify a figure and axes, then plot the image on the axes.
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_lights.jpeg')
plt.imshow(original,cmap='gray')
lower = 150
upper = 254
bright = cv2.inRange(original,lower,upper)
fig, ax = plt.subplots()
im = ax.imshow(bright,cmap='gray')
plt.show()
It helps to first convert your image as opencv image into the right color scale with cv2.COLOR_xxx:
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_light.jpg')
original = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
lower, upper = 150, 254
bright = cv2.inRange(image, lower, upper)
plt.imshow(bright,cmap='gray')
OpenCV imread functions reads the image in a B, G, R fashion.
Therefore if you read the image with imread and want to display with pyplot, first you need to convert the image into the R, G, B then display.
For instance:
import cv2
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv2.imread("lights.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
Result:
If you don't convert using cvtColor the result will be:
The above for the RGB images, for gray images the correct answer will be:
import cv2
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv2.imread("lights.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_rgb, cmap='gray')
plt.show()
lower = 150
upper = 254
bright = cv2.inRange(img_rgb, lower, upper)
plt.imshow(bright, cmap='gray')
plt.show()
Result:

PIL converting from I;16 to JPEG produce white image

I am having a problem converting an image I;16 to JPEG with PIL.
My original image can be found here (as pickle).
The original image comes from a DICOM file.
Here is the code to try:
import pickle
import matplotlib.pyplot as plt
from PIL import Image
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
rgb_im = img.convert("RGB")
print(rgb_im.mode)
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
Unfortunately the image is completely white, while it should be a chest x-ray scan image.
I followed this other stackoverflow question, and with the following
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
img.mode = 'I'
rgb_im = img.point(lambda i:i*(1./256)).convert('L')
rgb_im.save('my.jpeg')
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
I am able to visualise the image, but unfortunately my.jpeg is a black image. Please help!
Your values are 16-bit and need to be reduced to 8-bit for display. You can scale them from their current range of 2,712 (i.e. ims.min()) to 4,328 (i.e. ims.max()) with the following:
from PIL import Image
import numpy as np
import pickle
# Load image
ims = pickle.load(open("pixel_array.pickle", "rb"))
# Normalise to range 0..255
norm = (ims.astype(np.float)-ims.min())*255.0 / (ims.max()-ims.min())
# Save as 8-bit PNG
Image.fromarray(norm.astype(np.uint8)).save('result.png')

How to write lines and grid on image in Python?

import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
import Image
from scipy import ndimage
import Image, ImageDraw
import PIL
import cv
import cv2
from scipy.ndimage import measurements, morphology
from PIL import Image
from numpy import *
from scipy.ndimage import filters
import pylab
import mahotas
from mamba import*
import mambaDraw
from PIL import Image, ImageDraw
img = np.asarray(Image.open('test.tif').convert('L'))
img = 1 * (img < 127)
draw = ImageDraw.Draw(img)
draw.line((100,200, 150,300), fill=128)
plt.imshow(img, cmap=cm.Greys_r)
plt.show()
I want to put some grid lines on image, but get the following error:
Traceback (most recent call last):
File "C:\Documents and Settings\All Users.WINDOWS\Документыline 24, in <module>
draw = ImageDraw.Draw(img)
File "C:\Python27\lib\site-packages\PIL\ImageDraw.py", line 296, in Draw
return ImageDraw(im, mode)
File "C:\Python27\lib\site-packages\PIL\ImageDraw.py", line 61, in __init__
im.load()
AttributeError: 'numpy.ndarray' object has no attribute 'load'
What is wrong with this code? How do I put a 100x100 grid on an image?
Your error here is that you convert a PIL image to a numpy array, but then you use the PIL ImageDraw library on the numpy array.
You can draw the lines in either PIL or Numpy, whichever you prefer, but you need to use Numpy to work with Numpy objects and PIL to work with PIL objects. Saullo showed how to do it in PIL, in numpy you could do:
img[:, 100:110] = 0
or for a grid 10 pixels wide, every 100:
for i in range(100,1000,100):
img[i:i+10,:] = 0
img[:,i:i+10] = 0
As a side note, your imports are a bit crazy and are messing up your namespace. For what you're doing, you can just do:
import numpy as np
import Image, ImageDraw
# and for a reasonable import of other packages you've listed
from matplotlib import cm
from matplotlib import pyplot as plt
from scipy import ndimage
import cv2
import mahotas
import mambaDraw
For example, you only need one of from numpy import * or import numpy as np, but once you've already imported it, it complicates things to reimport it as some other name.
It seems you cannot convert it to a np.ndarray. Also, you should set the width parameter to a value different than 0:
import matplotlib.pyplot as plt
from matplotlib.pyplot import cm
from PIL import Image, ImageDraw
img = Image.open( 'test.tif' ).convert('L')
draw = ImageDraw.Draw(img)
draw.line((0,200, 1000,1000), fill=123., width=4)
plt.imshow(img, cmap=cm.Greys_r)
plt.savefig('test_changed.tif')

Reading TIFF in Python and Matplotlib using GDAL

I'm trying to display a grayscale TIFF file using Python and MatPlotLib,
So far I have read the file this:
import scipy as N
import gdal
import sys
import matplotlib.pyplot as pyplot
try:
tif = gdal.Open('filename.tif')
tifArray = tif.ReadAsArray()
except:
print 'The file does not exist.'
sys.exit(0)
band1 = tif.GetRasterBand(1)
band2 = tif.GetRasterBand(2)
band3 = tif.GetRasterBand(3)
band1Array = band1.ReadAsArray()
band2Array = band2.ReadAsArray()
band3Array = band3.ReadAsArray()
But then I don't know what else should I do... I'm so clueless.
Anyone would help me in this?
Once you processed your file into a 2 Array, you could use ANY function in matplotlib that plots 2D arrays, e.g. cmap, imshow etc.
Here is the output with the marbles example
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
img=mpimg.imread('MARBLES.TIF ')
imgplot = plt.imshow(img)
Here is what you get if you view only band3 of the image:
imgplot2 = plt.imshow(band3Array)
plt.show()
Look further into image viewing in MPL and 2D array functions...

Categories

Resources