Longji Vwamhi
Longji Vwamhi

Reputation: 21

Giving grayscale image color

edited image after assignment statement

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

Answers (2)

fmw42
fmw42

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:

enter image description here

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


enter image description here

Concatenate as many different colored pixels as you want to form a rainbow LUT, if desired.

Upvotes: 3

nathancy
nathancy

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

Related Questions