make all images' shape the same in python - python

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()

Related

Python OpenCV - How to recognize the specific colour in the image

Hello all I am working on the program that will simply recognize % of violet colour in the image. I am struggling with this rgb values.. Is there any smarter way of predefined static values for colours like 'blue' or 'green' or 'violet' in openCV already?
This is the code and the picture
import cv2
import numpy as np
imagePath = "probki/b.png"
img = cv2.imread(imagePath)
violet = [84, 39, 60]
diff = 100
boundaries = [([violet[2], violet[1]-diff, violet[0]-diff],
[violet[2]+diff, violet[1]+diff, violet[0]+diff])]
scalePercent = 1
width = int(img.shape[1] * scalePercent)
height = int(img.shape[0] * scalePercent)
newSize = (width, height)
img = cv2.resize(img, newSize, None, None, None, cv2.INTER_AREA)
cv2.imshow("img resized", img)
cv2.waitKey(0)
for (lower, upper) in boundaries:
lower = np.array(lower, dtype=np.uint8)
upper = np.array(upper, dtype=np.uint8)
mask = cv2.inRange(img, lower, upper)
cv2.imshow("binary mask", mask)
cv2.waitKey(0)
output = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("ANDed mask", output)
cv2.waitKey(0)
ratio_violet = cv2.countNonZero(mask)/(img.size/3)
colorPercent = (ratio_violet * 100) / scalePercent
print('violet pixel percentage:', np.round(colorPercent, 2))
cv2.imshow("images", np.hstack([img, output]))
cv2.waitKey(0)

How to change dimensions of np.array for greyscale images

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.

How concatenate gray and rgb channel of image using python

I have following code:
import cv2
import numpy as np
img = cv2.imread('a.jpg')
gray = cv2.imread('b.jpg')
gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
print('a shape:', img.shape) # a shape: (50,50,3)
print('b shape:', img.shape) # b shape: (50,50)
result = np.concatenate((img, gray), axis=2)
print('result: ', result.shape) # hope result shape: (50, 50, 4)
I get a exception as following :
ValueError: all the input arrays must have same number of dimensions
I want to get result.shape = (50, 50, 4), 4 channels. How to revise my code?
I believe you are looking for np.dstack:
result = np.dstack((img, gray))

BGR values of masked image (OpenCV, Python)

Using the follow image..
... I am applying this code to create a circle mask:
import cv2
import numpy as np
img = cv2.imread("car.png")
height, width, depth = img.shape
circle_img = np.zeros((height, width), np.uint8)
mask = cv2.circle(circle_img, (int(width / 2), int(height / 2)), 90, 1, thickness=-1)
masked_img = cv2.bitwise_and(img, img, mask=circle_img)
cv2.imshow("masked", masked_img)
cv2.waitKey(0)
This is the output..
How can I find BGR values of the circle using OpenCV ?
You can do it using numpy arrays.
circle_locations = mask == 1
bgr = img[circle_locations]
EDIT: I'm not sure if your mask has values in {0, 1} though I assume it does. If its background value is 0 and all positive values are forground, just change the == 1 to a > 1.

Resizing RGB image with cv2 numpy and Python 2.7

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)

Categories