I understand how to convert a BGR image to YCrCb format using cvtColor()
and separate different channels using split()
in OpenCV. However, these channels are displayed as grayscale images:
imgYCrCB = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
Y, Cr, Cb = cv2.split(imgYCrCB)
cv2.imshow("Y", Y)
cv2.imshow("Cr", Cr)
cv2.imshow("Cb", Cb)
cv2.waitKey(0)
This code give these results:
I would like to display Cb and Cr channels in color like this image:
How can I do it?
CodePudding user response:
You would need to apply a color map to each channel, something like:
Y_color = cv2.applyColorMap(Y, cv.COLORMAP_HSV)
cv2.imshow("Y", Y_color)
and so on
I have put the color map cv.COLORMAP_HSV
in this example, but I actually don't know what the best color map is, maybe you can try the ones in the documentation:
import cv2
import numpy as np
# read image
img = cv2.imread('barn.jpg')
hh, ww = img.shape[:2]
# convert to YCbCr
YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
# separate channels
Y, Cr, Cb = cv2.split(YCrCb)
# create a mid-gray constant image
gray = np.full((hh,ww), 128, dtype=np.uint8)
# invert Cr and Cb
Cr_inv = cv2.bitwise_not(Cr)
Cb_inv = cv2.bitwise_not(Cb)
# combine channels to get the Cr and Cb colorized images as if BGR
Cr_colored = cv2.merge([gray, Cr_inv, Cr])
Cb_colored = cv2.merge([Cb, Cb_inv, gray])
Y_colored = cv2.merge([Y, Y, Y])
# save results
cv2.imwrite('Y_colored.png', Y_colored)
cv2.imwrite('Cr_colored.png', Cr_colored)
cv2.imwrite('Cb_colored.png', Cb_colored)
# show results
cv2.imshow('Y_colored', Y_colored)
cv2.imshow('Cr_colored', Cr_colored)
cv2.imshow('Cb_colored', Cb_colored)
cv2.waitKey()
Y:
Cr:
Cb:
CodePudding user response:
The trick for getting the false colors effect for displaying Cb
and Cr
is relatively simple:
- For
Cb
false colors:
FillY
andCr
with value128
, and convert back to BGR. - For Cr false colors:
FillY
andCb
with value128
, and convert back to BGR. - Y is kept in Grayscale format.
Value 128 applies middle gray for Y.
When Cb=128, there are no "blue tones" (Cb
is "neutralized").
When Cr=128, there are no "red tones" (Cr
is "neutralized").
Code sample:
import cv2
import numpy as np
img = cv2.imread('rgb.png') # Read input image in BGR format
imgYCrCB = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # Convert RGB to YCrCb (Cb appiles V, and Cr applies U).
Y, Cr, Cb = cv2.split(imgYCrCB)
# Fill Y and Cb with 128 (Y level is middle gray, and Cb is "neutralized").
onlyCr = imgYCrCB.copy()
onlyCr[:, :, 0] = 128
onlyCr[:, :, 2] = 128
onlyCr_as_bgr = cv2.cvtColor(onlyCr, cv2.COLOR_YCrCb2BGR) # Convert to BGR - used for display as false color
# Fill Y and Cr with 128 (Y level is middle gray, and Cr is "neutralized").
onlyCb = imgYCrCB.copy()
onlyCb[:, :, 0] = 128
onlyCb[:, :, 1] = 128
onlyCb_as_bgr = cv2.cvtColor(onlyCb, cv2.COLOR_YCrCb2BGR) # Convert to BGR - used for display as false color
cv2.imshow('img', img)
cv2.imshow('Y', Y)
cv2.imshow('onlyCb_as_bgr', onlyCb_as_bgr)
cv2.imshow('onlyCr_as_bgr', onlyCr_as_bgr)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('Y.png', Y)
cv2.imwrite('onlyCb_as_bgr.png', onlyCb_as_bgr)
cv2.imwrite('onlyCr_as_bgr.png', onlyCr_as_bgr)