I tried to do this:
import cv2
color_image = cv2.imread('numbers/1.png')
gray_image = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
img_final = gray_image.reshape(28, 28, 1)
but I got (28, 1) array.
I wanted to utilize some images using CNN classification.
however, the problem is the image shape is different for example
for i in range(1,len(x_train)):
print(print(x_train_resize[i].shape))
this shows the images' shapes for all the images that i am using this gives output of
None
(100, 100)
None
(100, 100)
None
(100, 100, 3)
None
(100, 100, 4)
as shown above, is there a way to make the shapes of the images that i have all the same as
(100, 100, 1) or (100, 100, 3)
(100, 100) means grayscale image.
(100, 100, 3) means RGB image.
(100, 100, 4) means RGBA image.
If you have numpy grayscale image img_gray with shape (100,100) then you can duplicate layers to create (100, 100, 3) like in RGB
img_rgb = np.dstack((img_gray, img_gray, img_gray))
If you add alpha layer with values 255 then you get (100, 100, 4) like in RGBA
alpha = np.ones((100, 100), dtype='uint8') * 255
img_rgba = np.dstack((img_rgb, alpha))
If you have img_rgba with (100, 100, 4) then you can skip alpha layer to get img_rgb
img_rgb = img_rgba[:,:,:3]
to convert rgb to grayscale you could calculate
img_gray = (img_rgb[:,:,0] + img_rgb[:,:,1] + img_rgb[:,:,2]) // 3
but better is formula GRAY = 0.2126 * R + 0.7152 * G + 0.0722 * B
img_gray = int(0.2126 * img_rgb[:,:,0] + 0.7152 * img_rgb[:,:,1] + 0.0722 * img_rgb[:,:,2])
Wikipedia: Converting colour to greyscale
If you use OpenCV which also use numpy arrays then it has function to convert colors.
gray to RGB
img_rgb = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2RGB)
gray to RBGA
img_rgba = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2RGBA)
RGB to RBGA
img_rgba = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2RGBA)
and in other direction
RGB to gray
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
RBGA to gray
img_gray = cv2.cvtColor(img_rgba, cv2.COLOR_RGBA2GRAY)
RGBA to RBG
img_rgb = cv2.cvtColor(img_rgba, cv2.COLOR_RGBA2RGB)
You could also use pillow Image.convert but it needs to
convert numpy array to pillow Image - img = Image.fromarray(array),
convert color - img = img.convert(...),
convert back pillow Image to numpy array - array = np.asarray(img).
Doc: Image.fromarray()
EDIT:
Minimal working example
import numpy as np
img_gray = np.zeros((100, 100), dtype='uint8')
# create image with cross
for y in range(100):
img_gray[y,y] = int(255 * (y/100))
img_gray[y,99-y] = int(255 * (y/100))
print('img_gray.shape:', img_gray.shape) # (100, 100)
img_rgb = np.dstack((img_gray, img_gray, img_gray))
print('img_rgb.shape:', img_rgb.shape) # (100, 100, 3)
alpha = np.ones((100, 100), dtype='uint8') * 255
img_rgba = np.dstack((img_rgb, alpha))
print('img_rgba.shape:', img_rgba.shape)
import matplotlib.pyplot as plt
plt.imshow(img_gray)
plt.show()
plt.imshow(img_rgb)
plt.show()
plt.imshow(img_rgba)
plt.show()
# --- OpenCV ---
import cv2
img_cv2_rgb = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2RGB)
print('img_cv2_rgb.shape:', img_cv2_rgb.shape)
img_cv2_rgba = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2RGBA)
print('img_cv2_rgba.shape:', img_cv2_rgba.shape)
img_cv2_rgba2 = cv2.cvtColor(img_cv2_rgb, cv2.COLOR_RGB2RGBA)
print('img_cv2_rgba2.shape:', img_cv2_rgba2.shape)
cv2.imshow('gray', img_gray)
cv2.imshow('rgb', img_cv2_rgb)
cv2.imshow('rgba', img_cv2_rgba)
cv2.waitKey(0)
cv2.destroyAllWindows()
I want to create a blank image and first try converting a ndarray to PIL Image, however, generating the wrong image. Why does this strange thing happen?
from PIL import Image
import numpy as np
x = np.ones((256, 256)).astype(bool)
img = Image.new('1', (256, 256), 1)
y = np.asarray(img)
print((x == y).all())
# x equals to y, but ploting different pictures, why?
img1 = Image.fromarray(x, mode='1')
img1.show()
img2 = Image.fromarray(y, mode='1')
img2.show()
Change the mode to 8 bit pixels not only in Image.new but also in Image.fromarray:
from PIL import Image
import numpy as np
x = np.ones((256, 256)).astype(bool)
img = Image.new('L', (256, 256), 1)
y = np.asarray(img)
img1 = Image.fromarray(x, mode='L')
img1.show()
img2 = Image.fromarray(y, mode='L')
img2.show()
I have the following code to load an image:
img = imread(os.path.join('./Faces/','10.png'))
print(img.shape)
img = np.mean(img, axis=2)
img = img.astype(int)
print(img.shape)
The output of this code is as follows:
(200, 180, 3)
(200, 180)
I understand that I'm averaging out the RGB layers into a greyscale value, but I have my Keras input layer defined with shape (200, 280, 1). Is there a way to have the shape changed to this? Is there even a functional difference between having a matrix of the two shapes as outputted above?
You could use the expand_dims function in numpy (see documentation).
It works as follows in your case:
img = img.astype(int)
print(img.shape)
# Prints (100, 100)
img = np.expand_dims(img, axis=2)
print(img.shape)
# Prints (100, 100, 1)
You shouldn't average out the channels. There's a particular balance between the RGB channels to transform a picture to grayscale, and it's not conveniently 0.33% each. It's that:
((0.3*R) + (0.59*G) + (0.11*B))
Instead of averaging or doing it manually, I suggest that you use:
import cv2
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Then add a dimension:
img = img[..., np.newaxis]
or
img = np.expand_dims(img, -1)
The functional difference is that obviously, your CNN will not see color if you turn it into grayscale. So it won't be able to use this information to classify.
I want to resize an RGB image using Python 2.7. I tried using cv2.resize funcion, but it always returns a single channel image:
(Pdb) x = cv2.imread('image.jpg')
(Pdb) x.shape
(50, 50, 3)
(Pdb) x = cv2.resize(x, (40, 40))
(Pdb) x.shape
(40, 40)
I would like the final output of x.shape to be (40, 40, 3).
Is there a more pythonic way to resize the RGB image other than looping through the three channels and resizing each one separately?
Try this code:
import numpy as np
import cv2
image = cv2.imread('image.jpg')
cv2.imshow("Original", image)
"""
The ratio is r. The new image will
have a height of 50 pixels. To determine the ratio of the new
height to the old height, we divide 50 by the old height.
"""
r = 50.0 / image.shape[0]
dim = (int(image.shape[1] * r), 50)
resized = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)
cv2.imshow("Resized (Height) ", resized)
cv2.waitKey(0)