Reputation: 13
I want to merge RGB channel in the function I created after I normalized each channel with the value of r,g,b that I define before, here is the equation
def color_norm(image_norm):
pixels = np.array(image_norm)
ar_mean = np.mean(pixels, axis=(0,1))
(H,W) = image_norm.shape[:2]
for x in range(H):
for y in range(W):
Ri = image_norm[:,:,0]
Gi = image_norm[:,:,1]
Bi = image_norm[:,:,2]
R = Ri[x,y] = np.min((Ri[x,y]/(ar_mean[0]))*(r))
if R > 255:
# saturate value
R = 255
else:
# add normally
R = R
G = Gi[x,y] = np.min((Gi[x,y]/(ar_mean[1]))*(g))
if G > 255:
# saturate value
G = 255
else:
# add normally
G = G
B = Bi[x,y] = np.min((Bi[x,y]/(ar_mean[2]))*(b))
if B > 255:
# saturate value
B = 255
else:
# add normally
B = B
image_norm[x,y] = [R,G,B]
when I tried in single image it works,but when I pass this function to the dataset(contain 5 images) it raise an error TypeError: Image data of dtype object cannot be converted to float
anyone knows how to merge the RGB channel so that I can pass the function?
Upvotes: 1
Views: 470
Reputation: 1143
A full working code here
import cv2
import numpy as np
def color_norm(img, weights):
kb, kg, kr = weights
b = img[:, :, 0].astype(np.float32)
g = img[:, :, 1].astype(np.float32)
r = img[:, :, 2].astype(np.float32)
bm = np.mean(b)
gm = np.mean(g)
rm = np.mean(r)
img_out = np.empty_like(img, dtype=np.uint8)
img_out[:, :, 0] = np.minimum(b*kb/bm,255).astype(np.uint8)
img_out[:, :, 1] = np.minimum(g*kg/gm,255).astype(np.uint8)
img_out[:, :, 2] = np.minimum(r*kr/rm,255).astype(np.uint8)
return img_out
fin = r'D:\ColorfulMacaws-640x480.jpg'
img_bgr = cv2.imread(fin, cv2.IMREAD_COLOR)
cv2.imshow('Image before norm', img_bgr)
ws = (40, 50, 60)
imout = color_norm(img_bgr, ws)
cv2.imshow('Image after norm', imout)
cv2.waitKey(0)
cv2.destroyAllWindows()
Upvotes: 1
Reputation: 331
Based on the code I tried, here's a solution to your question.
import numpy as np
def normalize_to_grayscale(image: np.array, weights: tuple):
"""normalized a numpy array of an image to 0-255 interval , returning middle gray if all values are equal
Args:
image (np.array): input image
weights (tuple): tuple of len 3, with weights of the channels
Returns:
np.array: normalized array, same size as input image
"""
# Convert image to float
image = image.astype(float)
H, W, _ = image.shape
# Convert image to grayscale
image_gray = np.zeros((H, W))
for x in range(H):
for y in range(W):
image_gray[x, y] = np.sum(image[x, y] * weights)
# Normalize the image
image_gray -= (image_gray.min())
max_value = image_gray.max()
if max_value == 0:
return np.zeros((H, W)) + 127.5
image_gray *= (255.0/image_gray.max())
return image_gray
# Create sample image
img = np.array([[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
[[0, 0, 255], [255, 0, 0], [0, 255, 0]],
[[255, 0, 0], [0, 255, 0], [0, 0, 255]]])
weights = (1, 2, 3)
normalize_to_grayscale(img, weights)
It returns a result like this.
array([[ 0. , 127.5, 255. ],
[255. , 0. , 127.5],
[ 0. , 127.5, 255. ]])
Upvotes: 0