How to use Pillow instead cv2? - python

I have a small histogram program on Python, I want to use Pillow library instead of cv2.
from PIL import Image
import cv2
import matplotlib.pyplot as plt
im = cv2.imread('pic.jpg')
im.ndim == 3:
# Input image is three channels
fig = plt.figure()
fig.add_subplot(311)
plt.hist(im[...,0].flatten(), 256, range=(0, 250), fc='b')
fig.add_subplot(312)
plt.hist(im[...,1].flatten(), 256, range=(0, 250), fc='g')
fig.add_subplot(313)
plt.hist(im[...,2].flatten(), 256, range=(0, 250), fc='r')
plt.show()
I can replace im = cv2.imread('pic.jpg') to im = Image.open('pic.jpg') and im.ndim to im.getbands(), but what can i do with im[...,0].flatten()?

In Python opencv uses numpy arrays as data structures for images. So cv2.imread returns a numpy array.
Matplotlib has a similar function, so for the example in your question you need neither opencv nor pil:
import matplotlib.pyplot as plt
im = plt.imread('pic.jpg')
if im.shape[2] == 3:
# Input image is three channels
fig = plt.figure()
fig.add_subplot(311)
plt.hist(im[...,0].flatten(), 256, range=(0, 250), fc='b')
fig.add_subplot(312)
plt.hist(im[...,1].flatten(), 256, range=(0, 250), fc='g')
fig.add_subplot(313)
plt.hist(im[...,2].flatten(), 256, range=(0, 250), fc='r')
plt.show()
If you have to use PIL to load the image, then you can convert it to a numpy array before plotting:
from PIL import Image
import numpy as np
im = np.array(Image.open('pic.jpg'))

This is how to get pixel values (from 0 to 255) of an image using pillow:
from PIL import Image # import library
import numpy as np # import library
img = Image.open('myImage.png') # use Image.open(image_location)
image_data = np.array(img) # to convert img object to array value use np.array
print(image_data) # now, print all the pixel values of image in np array

Related

how to add data to cvlib

Does anyone knows how to add data to cvlib? I want to use
cv.detect_common_objects with my own data.
I was trying to do ant recogniton but cvlib doesn't have any ant data. I have to get answer fast.
code:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import cvlib as cv
from cvlib.object_detection import draw_bbox
from numpy.lib.polynomial import poly
#wcale nie z poradnika :D
img = cv2.imread("ant1.png")
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(10, 10))
plt.axis("off")
plt.imshow(img1)
plt.show()
box, label, count = cv.detect_common_objects(img)
output = draw_bbox(img, box, label, count)
output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(10, 10))
plt.axis("off")
plt.imshow(output)
plt.show()

How to make colormaps for this image in python m?

I want to make a colormap used in the attached image colorbar. I could do it MATLAB, however, I can't seem to do it in python. So far I tried the code given below but didn't get the result I was looking for.
img = imread('/path/colorbarimage.png')
colors_from_img = img[:, 0, :]
my_cmap = LinearSegmentedColormap.from_list('my_cmap', colors_from_img, N=651)
y = random_sample((100, 100))
imshow(y, cmap=my_cmap);plt.colorbar()
With img[:, 0, :] you're not picking the correct column in the colorbar image (if indeed colorbarimage.png is the image you linked).
The following works fine:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
img = plt.imread('colorbarimage.png')
# to check the selected rectangle:
cropped_cmap = img[145:799, 70:80, :]
plt.imshow(cropped_cmap)
plt.show()
colors_from_img = img[145:799, 74, :]
my_cmap = LinearSegmentedColormap.from_list('my_cmap', colors_from_img, N=256)
y = np.random.random_sample((100, 100))
plt.imshow(y, cmap=my_cmap)
plt.colorbar()
plt.show()

How to invert axis of a pillow image

Seaborn offers the possibility to invert the axis of an image. I would like to do the same with PIL. Here is my code.
# Imports
import seaborn as sns; sns.set_theme()
import matplotlib.pyplot as plt
import numpy as np
import numpy as np; np.random.seed(0)
from PIL import Image
import random
# Arrays
r = []
g = []
b = []
for i in range(200):
r.append(random.sample(range(0, 255), 200))
g.append(random.sample(range(0, 255), 200))
b.append(random.sample(range(0, 255), 200))
# Change color of the left part of the image
r = np.array(r)
r[:, 0:10]=0
# Change color of the right part of the image
r = np.array(r)
r[:, -10:-1]=150
g = np.array(g)
g[:, -10:-1]=150
# Plot seaborn heatmap
fig, ax = plt.subplots()
sax = sns.heatmap(r)
sax.invert_xaxis()
sax.invert_xaxis() inverts the x-axis of the plot.
I would like to do the same with pillow. I have been google it for a long time without finding anything.
Here is my rgb pillow image.
rgbarr = np.zeros((200,200,3), 'uint8')
rgbarr[..., 0] = np.array(r)
rgbarr[..., 1] = np.array(g)
rgbarr[..., 2] = np.array(b)
img = Image.fromarray(rgbarr)
img
opencv possibility would also be welcome.
I think you just want to flip it:
im_flipped = im.transpose(method=Image.FLIP_LEFT_RIGHT)

How to put all pixels of an image with the method reshape in Python?

I have an image of shape (271, 300, 3) containing values between 0 and 1 (image/255)
And I would like to put all the pixels of this image in another variable (pixel) with the method reshape, how to do that ? Here is my few code
image = plt.imread('im3.jpg')
im = image/255.0
print(im.shape) #(271, 300, 3)
Until here, I've tried to do that :
pixels = im.reshape(im.shape[0]*im.shape[1]*im.shape[2])
but I don't think it is the way to do that.
To reshape it to flat array with pixels which have three values (R,G,B)
pixels = im.reshape( im.shape[0]*im.shape[1], im.shape[2] )
It will convert (271, 300, 3) to (81300, 3)
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
image = plt.imread('im3.jpg')
im = image/255.0
print(im.shape) #(271, 300, 3)
pixels = im.reshape(im.shape[0]*im.shape[1], im.shape[2])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(pixels[:,0], pixels[:,1], pixels[:,2], c=pixels)
plt.show()

Combine picture and plot with matplotlib with alpha channel

I have a .png image with alpha channel and a random pattern generated with numpy.
I want to supperpose both images using matplotlib. The bottom image must be the random pattern and over this, I want to see the second image (attached in the end of the post).
The code for both images is the following:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
# Random image pattern
fig = plt.subplots(figsize = (20,4))
x = np.arange(0,2000,1)
y = np.arange(0,284,1)
X,Y = np.meshgrid(x,y)
Z = 0.6+0.1*np.random.rand(284,2000)
Z[0,0] = 0
Z[1,1] = 1
# Plot the density map using nearest-neighbor interpolation
plt.pcolormesh(X,Y,Z,cmap = cm.gray)
The result is the following image:
To import the image, I use the following code:
# Sample data
fig = plt.subplots(figsize = (20,4))
# Plot the density map using nearest-neighbor interpolation
plt.imread("good_image_2.png")
plt.imshow(img)
print(img.shape)
The image is the following:
Thus, the final result that I want is:
You can make an image-like array for Z and then just use imshow to display it before the image of the buttons, etc. Note that this only works because your png has an alpha channel.
Code:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
# Plot the density map using nearest-neighbor interpolation
img = plt.imread("image.png")
(xSize, ySize, cSize) = img.shape
x = np.arange(0,xSize,1)
y = np.arange(0,ySize,1)
X,Y = np.meshgrid(x,y)
Z = 0.6+0.1*np.random.rand(xSize,ySize)
Z[0,0] = 0
Z[1,1] = 1
# We need Z to have red, blue and green channels
# For a greyscale image these are all the same
Z=np.repeat(Z,3).reshape(xSize,ySize,3)
fig = plt.figure(figsize=(20,8))
ax = fig.add_subplot(111)
ax.imshow(Z, interpolation=None)
ax.imshow(img, interpolation=None)
fig.savefig('output.png')
Output:
You can also turn off axes if you prefer.
ax.axis('off')

Categories

Resources