How to create a "bluescale" image

Viewed 283

How to create an image manipulation effect similar to this website using opencv:

https://manytools.org/image/colorize-filter/

original enter image description here

processed enter image description here

I tried to keep the blue channel, or fill the grayscale image to it, and the red and green channels are reduced to 0, but they are not helpful, any help is grateful.

4 Answers

@Suphanut had the right idea but didn't flesh it out. I used your example image to create a custom color map. The result is not perfect, but it's very close. The difference is most apparent in the edge of the wheel well. I suspect it's a difference in the way your reference software and cv2 convert an image to gray scale.

enter image description here

import cv2
img = cv2.imread(r'car.jpg', cv2.IMREAD_GRAYSCALE)
lut = np.array([
    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],
    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],
    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],
    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],
    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],    [[0,0,0]],
    [[0,0,0]],    [[1,0,0]],    [[1,0,0]],    [[2,0,0]],
    [[2,0,0]],    [[3,0,0]],    [[7,0,0]],    [[13,0,0]],
    [[19,0,0]],    [[23,0,0]],    [[24,0,0]],    [[24,0,0]],
    [[25,0,0]],    [[27,0,0]],    [[27,0,0]],    [[28,0,0]],
    [[30,0,0]],    [[32,0,0]],    [[33,0,0]],    [[33,0,0]],
    [[34,0,0]],    [[36,0,0]],    [[39,0,0]],    [[40,0,0]],
    [[41,0,0]],    [[45,0,0]],    [[48,0,0]],    [[48,0,0]],
    [[49,0,0]],    [[53,0,0]],    [[56,0,0]],    [[58,0,0]],
    [[64,0,0]],    [[67,0,0]],    [[69,0,0]],    [[71,0,0]],
    [[75,0,0]],    [[78,0,0]],    [[80,0,0]],    [[82,0,0]],
    [[85,0,0]],    [[88,0,0]],    [[89,0,0]],    [[91,0,0]],
    [[94,0,0]],    [[96,0,0]],    [[99,0,0]],    [[103,0,0]],
    [[106,0,0]],    [[107,0,0]],    [[110,0,0]],    [[111,0,0]],
    [[113,0,0]],    [[113,0,0]],    [[117,0,0]],    [[117,0,0]],
    [[121,0,0]],    [[124,0,0]],    [[129,0,0]],    [[132,0,0]],
    [[136,0,0]],    [[138,0,0]],    [[138,0,0]],    [[139,0,0]],
    [[141,0,0]],    [[144,0,0]],    [[144,0,0]],    [[144,0,0]],
    [[145,0,0]],    [[149,0,0]],    [[149,0,0]],    [[151,0,0]],
    [[154,0,0]],    [[155,0,0]],    [[157,0,0]],    [[159,0,0]],
    [[161,0,0]],    [[164,0,0]],    [[165,0,0]],    [[167,0,0]],
    [[169,0,0]],    [[172,0,0]],    [[174,0,0]],    [[175,0,0]],
    [[178,0,0]],    [[181,0,0]],    [[184,0,0]],    [[186,0,0]],
    [[189,0,0]],    [[191,0,0]],    [[195,0,0]],    [[198,0,0]],
    [[201,0,0]],    [[203,0,0]],    [[206,0,0]],    [[209,0,0]],
    [[212,0,0]],    [[216,0,0]],    [[218,0,0]],    [[222,0,0]],
    [[224,0,0]],    [[227,1,1]],    [[230,1,1]],    [[233,1,1]],
    [[236,1,1]],    [[239,2,2]],    [[241,2,2]],    [[243,3,3]],
    [[246,4,4]],    [[248,5,5]],    [[250,6,6]],    [[252,7,7]],
    [[253,9,9]],    [[254,12,12]],    [[255,15,15]],    [[255,18,18]],
    [[255,21,21]],    [[255,25,25]],    [[255,29,29]],    [[255,31,31]],
    [[255,36,36]],    [[255,38,38]],    [[255,42,42]],    [[255,46,46]],
    [[255,50,50]],    [[255,53,53]],    [[255,57,57]],    [[255,60,60]],
    [[255,62,62]],    [[255,65,65]],    [[255,68,68]],    [[255,71,71]],
    [[255,74,74]],    [[255,76,76]],    [[255,80,80]],    [[255,82,82]],
    [[255,86,86]],    [[255,88,88]],    [[255,91,91]],    [[255,93,93]],
    [[255,97,97]],    [[255,99,99]],    [[255,102,102]],    [[255,105,105]],
    [[255,108,108]],    [[255,112,112]],    [[255,117,117]],    [[255,118,118]],
    [[255,121,121]],    [[255,122,122]],    [[255,125,125]],    [[255,126,126]],
    [[255,129,129]],    [[255,131,131]],    [[255,133,133]],    [[255,135,135]],
    [[255,139,139]],    [[255,144,144]],    [[255,147,147]],    [[255,152,152]],
    [[255,154,154]],    [[255,157,157]],    [[255,162,162]],    [[255,164,164]],
    [[255,168,168]],    [[255,170,170]],    [[255,174,174]],    [[255,177,177]],
    [[255,180,180]],    [[255,185,185]],    [[255,188,188]],    [[255,191,191]],
    [[255,193,193]],    [[255,196,196]],    [[255,198,198]],    [[255,200,200]],
    [[255,202,202]],    [[255,204,204]],    [[255,206,206]],    [[255,209,209]],
    [[255,212,212]],    [[255,214,214]],    [[255,216,216]],    [[255,218,218]],
    [[255,221,221]],    [[255,223,223]],    [[255,225,225]],    [[255,227,227]],
    [[255,228,228]],    [[255,230,230]],    [[255,231,231]],    [[255,234,234]],
    [[255,235,235]],    [[255,238,238]],    [[255,238,238]],    [[255,241,241]],
    [[255,242,242]],    [[255,244,244]],    [[255,247,247]],    [[255,249,249]],
    [[255,250,250]],    [[255,253,253]],    [[255,253,253]],    [[255,254,254]],
    [[255,254,254]],    [[255,253,253]],    [[255,252,252]],    [[255,253,253]],
    [[255,254,254]],    [[255,254,254]],    [[255,254,254]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],
    [[255,255,255]],    [[255,255,255]],    [[255,255,255]],    [[255,255,255]]],
    dtype=np.uint8)
cv2.imshow('cv2', cv2.applyColorMap(img, lut))

Obviously I hard coded the conversion look-up table, but with a little more analysis it might be possible to create a formula that would generate it simply.

You can try convert RGB to BGR by using cv2.cvtColor or apply colormap with cv2.applyColorMap

import cv2
img = cv2.imread("car.jpg")
# First method
img_bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
# Second method
img_ocean = cv2.applyColorMap(img, cv2.COLORMAP_OCEAN)

Here are example outputs for img_bgr and img_ocean. Hope it helps.

enter image description here enter image description here

Edited: You can also try customize your own ColorMap

I manage to get a similar effect by first converting the image to the HSV colorspace, and then adjusting the hue value to 120 (which represents the OpenCV conversion of the blue [255, 0, 0].

With this I got this picture:

hsv conversion

Using the following code:

import cv2

img = cv2.imread("./EZCUD.jpg")
img_blue = img.copy()
img_blue = cv2.cvtColor(img_blue, cv2.COLOR_BGR2HSV)
img_blue[:, :, 0] = 120
cv2.imwrite("./test.jpg", cv2.cvtColor(img_blue, cv2.COLOR_HSV2BGR))

Edit:

I managed to get a much better result by applying a gamma correction on the independent BGR channels after the HSV processing. I normalize the image to the range [0,1] and took square power in the RG channels and took the square root in the Blue channel.

This is the result:

final img

With the following code:

import cv2
import numpy as np

img = cv2.imread("./EZCUD.jpg")
img_blue = img.copy()

img_blue = cv2.cvtColor(img_blue, cv2.COLOR_BGR2HSV)
img_blue[:, :, 0] = 120
img_blue = cv2.cvtColor(img_blue, cv2.COLOR_HSV2BGR)
img_blue = img_blue.astype("float")
img_blue /= 255
img_blue[:, :, 1:] = img_blue[:, :, 1:] ** 2
img_blue[:, :, 0] = img_blue[:, :, 0] ** (1 / 2)
img_blue *= 255

cv2.imwrite("./test.jpg", img_blue.astype("uint8"))

You can play around with these parameters until the result is closer to what you expected.

Generate template image:

import cv2

img=np.array([[x for x in range(256)]]*128,dtype='uint8')

cv2.imshow('',img)
cv2.imwrite('gradient.jpg',img)

enter image description here

Generate results on demand from website

enter image description here

Apply the template to the input image:

import numpy as np
import cv2

img=cv2.imread('processed.jpg')
img2=cv2.imread('in2.jpg')

line=img[0]
line=line.reshape(line.shape[0],1,-1)

result=cv2.applyColorMap(img2,line)

cv2.imshow('result',result)
cv2.waitKey()

enter image description here

input image:

enter image description here

Related