Reputation: 21
I want to add color to a black and white image, I assume that changing the values of the pixels should work.
for rows in rgb:
for e in rows:
for i in range(len(e)):
max_val = e.max()
min_val = e.min()
if e[i] == max_val:
e[i] * 2.5
if e[i] == min_val:
e[i] * 0.75
else:
e[i] * 1.5
the code doesnt return an error, but it also doesnt change the values. I want the numbers to be multiplied and reassigned by the same array
Upvotes: 2
Views: 6288
Reputation: 53089
Here is one way to apply a gradient color to a grayscale image.
Load the grayscale image
Convert it to 3 equal channels
Create a 1 pixel red image
Create a 1 pixel blue image
Concatenate the two
Resize linearly to 256 pixels as a Lookup Table (LUT)
Apply the LUT
Input:
import cv2
import numpy as np
# load image as grayscale
img = cv2.imread('lena_gray.png', cv2.IMREAD_GRAYSCALE)
# convert to 3 equal channels
img = cv2.merge((img, img, img))
# create 1 pixel red image
red = np.zeros((1, 1, 3), np.uint8)
red[:] = (0,0,255)
# create 1 pixel blue image
blue = np.zeros((1, 1, 3), np.uint8)
blue[:] = (255,0,0)
# append the two images
lut = np.concatenate((red, blue), axis=0)
# resize lut to 256 values
lut = cv2.resize(lut, (1,256), interpolation=cv2.INTER_CUBIC)
# apply lut
result = cv2.LUT(img, lut)
# save result
cv2.imwrite('lena_red_blue_lut_mapped.png', result)
# display result
cv2.imshow('RESULT', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Concatenate as many different colored pixels as you want to form a rainbow LUT, if desired.
Upvotes: 3
Reputation: 46600
Instead of manually iterating through each pixel which has an inefficient O(n^3)
run-time, we can take advantage of Numpy's broadcasting feature.
We first split the grayscale image into individual BGR
channels using cv2.split()
. This will give us separate B
, G
, and R
channels each with the same values. Next we multiply each channel with a scalar value using np.multiply()
. Finally we combine each individual channel into a color image using cv2.merge()
to create a single multi-channel array
Before
>>> print(before.shape)
(331, 500, 3)
You might be wondering why the image has three channels even though it's obviously grayscale. Well it's because each channel has the same values ranging from [0 ... 255]
After
>>> print(after.shape)
(331, 500, 3)
Again, same number of channels, but we modified each individual channel
TLDR: To add color to a black and white image, we have to extract each individual BGR
channel, modify each channel, then reconstruct the image
import cv2
import numpy as np
before = cv2.imread('2.png')
b, g, r = cv2.split(before)
np.multiply(b, 1.5, out=b, casting="unsafe")
np.multiply(g, .75, out=g, casting="unsafe")
np.multiply(r, 1.25, out=r, casting="unsafe")
after = cv2.merge([b, g, r])
cv2.imshow('before', before)
cv2.imshow('after', after)
cv2.waitKey()
Upvotes: 3