- 本篇文章记录学习如何将图像从一种颜色空间转换为另一种颜色空间,例如BGR<–>Gray,BGR <–>HSV,BGR<–>Yuv,BGR<–>Ycrcb等。
- 创建一个应用程序,从一幅图像中获取某个特定颜色的物体。
- 学习以下函数:cv2.cvtColor(),cv2.inRange() 等。
更改色彩空间
OpenCV提供了150多种颜色空间转换方法。但是,经常用的也就两种,即BGR<–>Gray和BGR <–>HSV。
对于颜色转换,我们使用函数cv2.cvtColor(input_image, flag)实现,flag就是转换类型。
对于BGR -->灰色转换,使用标志cv2.COLOR_BGR2GRAY。同样,对于BGR–>HSV,使用标志cv2.COLOR_BGR2HSV。
对于HSV,H(色彩/色度)范围为[0,179],S(饱和度)范围为[0,255],V(亮度)值范围为[0,255]。但是不同的软件使用不同的比例。因此,如果将OpenCV值与它们进行比较,则需要进行归一化处理。
下面用代码实现我们提到的色彩空间的转换。
import cv2 as cv
import numpy as np
# 颜色空间转换,从bgr到gray,hsv,yuv,ycrcb
def color_space_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
cv.imshow("hsv", hsv)
yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV)
cv.imshow("yuv", yuv)
ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)
cv.imshow("ycrcb", ycrcb)
if __name__ == '__main__':
src = cv.imread("F:/Pycharm/opencv_exercises-master/images/Crystal.jpg") # 读入图片放进src中
cv.namedWindow("Crystal Liu", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整
cv.imshow("Crystal Liu", src) # 将src图片放入该创建的窗口中
color_space_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
效果如图所示:
图像通道的分离与合并
分离:split()函数,合并:merge()函数
图像颜色通道的分离:
import cv2 as cv
import numpy as np
# 对图片三个通道颜色提取并放在三张图片中
def channels_split_merge(image):
b, g, r = cv.split(image) # b通道提取时,对该通道颜色保留,其余通道置为0
cv.imshow("blue", b)
cv.imshow("green", g)
cv.imshow("red", r)
执行结果:
刚开始很好奇为什么得到的是三张不同灰度图?不是已经分离出R,G,B通道了吗?应该是蓝色图,绿色图,红色图啊。
原因是:当调用cv.imshow(“blue”, b)时,是把图像的R,G,B三个通道的值都变为R的值,所以图像的颜色三通道值为(B,B,B)同理 cv.imshow(“green”, g)、cv.imshow(“red”, r)所显示图像的颜色通道也依次为(G,G,G)和(R,R,R)。而当三个通道d值相同时,则为灰度图。
下面将使用merge()函数将某一颜色通道(如R)与零矩阵合并,形成(R,0,0)从而显示只有红色通道的图,opencv中,图像的第一通道是B,第二通道是G,最后是R
zeros = np.zeros(image.shape[:2], dtype="uint8") # 创建与image相同大小的零矩阵
cv.imshow("BLUE", cv.merge([b, zeros, zeros])) # 显示 (B,0,0)图像
cv.imshow("GREEN", cv.merge([zeros, g, zeros])) # 显示(0,G,0)图像
cv.imshow("RED", cv.merge([zeros, zeros, r])) # 显示(0,0,R)图像
最后把分离出来的R,G,B通道的值重新合并在一起,看是否能获得原图:
完整工程代码:
import cv2 as cv
import numpy as np
# 颜色空间转换,从bgr到gray,hsv,yuv,ycrcb
def color_space_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
cv.imshow("hsv", hsv)
yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV)
cv.imshow("yuv", yuv)
ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)
cv.imshow("ycrcb", ycrcb)
# 对图片三个通道颜色提取并放在三张图片中
def channels_split_merge(image):
b, g, r = cv.split(image) # b通道提取时,对该通道颜色保留,其余通道置为0
# cv.imshow("blue", b)
# cv.imshow("green", g)
# cv.imshow("red", r)
zeros = np.zeros(image.shape[:2], dtype="uint8") # 创建与image相同大小的零矩阵
cv.imshow("BLUE", cv.merge([b, zeros, zeros])) # 显示 (B,0,0)图像
cv.imshow("GREEN", cv.merge([zeros, g, zeros])) # 显示(0,G,0)图像
cv.imshow("RED", cv.merge([zeros, zeros, r])) # 显示(0,0,R)图像
merge_image = cv.merge([b, g, r])
cv.imshow("merge_image", merge_image)
if __name__ == '__main__':
src = cv.imread(
"F:/Pycharm/opencv_exercises-master/images/Crystal.jpg") # 读入图片放进src中
cv.namedWindow("Crystal Liu", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整
cv.imshow("Crystal Liu", src) # 将src图片放入该创建的窗口中
# color_space_demo(src)
channels_split_merge(src)
cv.waitKey(0)
cv.destroyAllWindows()