opencv 中有几百种颜色空间,可通过如下方式获取;
flags = [i for i in dir(cv) if i.startswith('COLOR')] print(len(flags)) # 296 种
其中最常用的是 gray 和 hsv 空间;
颜色空间转换
opencv 默认读取图片是 BGR 空间,使用 cvtColor 转换到 其他空间
def cvtColor(src, code, dst=None, dstCn=None)
code 表示 转换方式
示例
### BGR --> GRAY img = cv.imread('imgs/2.png') img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY) cv.imshow('img', img) cv.imshow('gray', img_gray) cv.waitKey(0)

### BGR --> HSV img = cv.imread('imgs/2.png') img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) cv.imshow('img', img) cv.imshow('hsv', img_hsv) cv.waitKey(0)

HSV 空间
在 RGB 空间中,颜色会受到光照影响,且 3个通道也会彼此影响,无法准确描述像素;
在 HSV 空间中,三者相互独立,可准确描述像素的 亮度、饱和度、色调
H(色调):用角度度量,取值范围为0°~360° 颜色的深浅
S(饱和度,深度):表示颜色接近光谱色的程度。通常取值范围为0%~100%,值越大,颜色越饱和。 颜色的分离被定义为饱和度
V(明度):表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。

1. 在HSV中比在BGR颜色空间中 更容易表示颜色;
2. HSV对外部照明的微小变化更敏感。它将提供更准确的掩膜,从而获得更好的结果。
============== 2023.2.22 更新 ==============


原图,色度,饱和度,亮度
tricks
1. 在HSV域对V分量使用gamma校正改善亮度问题、或者使用直方图均衡处理V通道提高图像对比度,然后再合并
============== ============== ==============
YCrCb颜色空间
自适应直方图均衡化(CLAHE)可以应用于彩色图像。通常的做法是将彩色图像从 RGB颜色空间转换到其他颜色空间(如YUV、YCrCb 或 LAB),然后仅对亮度通道(通常是 Y 通道)应用 CLAHE,最后再将图像转换回 RGB 颜色空间。
这样可以避免在增强亮度的同时影响颜色平衡。
以下是一个示例代码,展示如何在OpenCV 中对彩色图像应用CLAHE:
import cv2 #读取彩色图像 image = cv2.imread('input_image.jpg' #将图像从 BGR 转换为 YCrCb颜色空间 yuv_image = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb) 离r通道 y,cr,cb= cv2.split(yuv_image) #创建CLAHE 对象 Clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) #应用 CLAHE 到高度通道 Y cl y=clahe.apply(y) # 合并处理后的 Y 通道和原始 Cr、Cb 通道 cl_yuv_image -cv2.merge([cl_y,cr,cb]) #将图像从 YCrCb 转换回 BGR 颜色空间 cl_image = cv2.cvtColor(cl_yuv_image, cv2.COLOR_YCrCb28GR) #显示结果 Cv2.imshow('Original Image',image) CV2.imshow('CLAHE Enhanced Image',cl_image) cv2.waitkey(0) cv2.destroyAllWindows()
YCrCb:Y 通道表示亮度,Cr 和Cb 通道表示色度。对 Y 通道进行 CLAHE处理可以增强图像的亮度对比度,而不影响颜色。
LAB颜色空间
LAB:L通道表示亮度,A和B通道表示颜色。对L通道进行CLAHE 处理同样可以增强图像的亮度对比度,而不影响颜色。
import cv2 #读取彩色图像 image =cv2.imread('input_image.jpg') #将图像从 BGR 转换为 LAB 颜色空间 lab_image = cv2.cvtColor(image,cv2.COLOR_BGR2LAB) #分离 L、A、B通道 l,a,b=cv2.split(lab_image) #创建 CLAHE 对象 clahe =cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) #应用 CLAHE 到亮度通道L cl_1=clahe.apply(1) #合并处理后的L通道和原始A、B通道 c1_1ab_image =cv2.merge([cl_1,a,b]) #将图像从 LAB 转换回 BGR颜色空间 cl_image = cv2.cvtColor(cl_1ab_image,cv2.COLOR_LAB2BGR) #显示结果 cv2.imshow('Original Image',image)25 cv2.imshow('CLAHE Enhanced Image',cl_image) cv2.waitKey(0) cv2.destroyA11Windows()
综合对比
将图像在RGB、灰度、HSV、LAB颜色空间进行对比展示的Python程序
import cv2 import numpy as np import matplotlib.pyplot as plt # 设置中文显示(如果系统没有SimHei字体,可改用英文标签) plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False def show_color_spaces(image_path): """ 展示图像在 RGB、灰度、HSV、LAB 颜色空间下的对比图 """ # 1. 读取图像 # OpenCV 默认读取为 BGR 格式 img_bgr = cv2.imread(image_path) if img_bgr is None: raise FileNotFoundError(f"无法读取图像: {image_path}") # 2. 转换为不同颜色空间 # BGR -> RGB img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # BGR -> 灰度 img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) # BGR -> HSV img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) # BGR -> LAB img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB) # 3. 将 HSV 和 LAB 分离通道用于可视化(单通道灰度图) h, s, v = cv2.split(img_hsv) l, a, b = cv2.split(img_lab) # 4. 创建对比图 fig, axes = plt.subplots(2, 4, figsize=(18, 9)) fig.suptitle('图像在不同颜色空间下的对比', fontsize=18, fontweight='bold') # 第一行:完整颜色空间 axes[0, 0].imshow(img_rgb) axes[0, 0].set_title('RGB 空间') axes[0, 1].imshow(img_gray, cmap='gray') axes[0, 1].set_title('灰度空间 (Gray)') # HSV 和 LAB 可视化:需要转回 RGB 才能正确显示(因为 matplotlib 按 RGB 解释) img_hsv_display = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB) axes[0, 2].imshow(img_hsv_display) axes[0, 2].set_title('HSV 空间') img_lab_display = cv2.cvtColor(img_lab, cv2.COLOR_LAB2RGB) axes[0, 3].imshow(img_lab_display) axes[0, 3].set_title('LAB 空间') # 第二行:各通道分量 axes[1, 0].imshow(img_rgb[:, :, 0], cmap='Reds') axes[1, 0].set_title('RGB - R 通道') axes[1, 1].imshow(h, cmap='hsv') axes[1, 1].set_title('HSV - H 通道 (色调)') axes[1, 2].imshow(a, cmap='coolwarm') axes[1, 2].set_title('LAB - A 通道 (绿-红)') axes[1, 3].imshow(b, cmap='coolwarm') axes[1, 3].set_title('LAB - B 通道 (蓝-黄)') # 去除坐标轴 for ax in axes.flat: ax.axis('off') plt.tight_layout() plt.savefig('color_spaces_comparison.png', dpi=150, bbox_inches='tight') plt.show() print("对比图已保存为 color_spaces_comparison.png") def show_side_by_side(image_path): """ 更简洁的 2x2 布局对比图 """ img_bgr = cv2.imread(image_path) if img_bgr is None: raise FileNotFoundError(f"无法读取图像: {image_path}") img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB) # 将 HSV、LAB 转回 RGB 用于显示 img_hsv_display = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB) img_lab_display = cv2.cvtColor(img_lab, cv2.COLOR_LAB2RGB) fig, axes = plt.subplots(2, 2, figsize=(12, 10)) fig.suptitle('RGB / 灰度 / HSV / LAB 对比', fontsize=16) axes[0, 0].imshow(img_rgb); axes[0, 0].set_title('RGB') axes[0, 1].imshow(img_gray, cmap='gray'); axes[0, 1].set_title('灰度 Gray') axes[1, 0].imshow(img_hsv_display); axes[1, 0].set_title('HSV') axes[1, 1].imshow(img_lab_display); axes[1, 1].set_title('LAB') for ax in axes.flat: ax.axis('off') plt.tight_layout() plt.show() if __name__ == '__main__': # 替换成你的图片路径 image_path = 'test.jpg' show_color_spaces(image_path)
各颜色空间特点
| 颜色空间 | 通道 | 特点与用途 |
|---|---|---|
| RGB | R、G、B | 面向硬件的加色模型,适合显示,但不利于颜色分割 |
| Gray | 单通道 | 亮度信息,用于边缘检测、模板匹配 |
| HSV | H(色调)、S(饱和度)、V(明度) | 贴近人类感知,颜色分割的首选 |
| LAB | L(亮度)、A(绿-红)、B(蓝-黄) | 设备无关,色差计算(ΔE),颜色校正 |
使用方法
对各颜色空间的 亮度 通道进行 CLAHE处理可以增强图像的亮度对比度,而不影响颜色
OpenCV 转换注意事项
# ⚠️ OpenCV 默认是 BGR,不是 RGB! img_bgr = cv2.imread('test.jpg') # BGR img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # HSV 的 H 范围是 0-179(不是 0-360) img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) # LAB 的 L 范围 0-255, A/B 范围 0-255(有偏移128) img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)
常见坑点
-
matplotlib 显示 HSV/LAB 原图会失真:必须
cvtColor转回 RGB 才能正确显示,否则颜色会很奇怪。 -
中文乱码:如果
SimHei不存在,可改为英文标签或安装中文字体。 -
cv2.imshow 显示 HSV/LAB:OpenCV 会把三通道当作 BGR,同样会失真,建议也转回 BGR 显示。
对象追踪 - 颜色空间的简单应用
利用像素实现对象跟踪,这是最简单的跟踪方式;
步骤:取视频的每一帧 - 从BGR转换到HSV颜色空间 - 对HSV图像设置蓝色范围的阈值 - 掩膜单独提取蓝色对象
代码
cap = cv.VideoCapture(0) while(1): # 读取帧 _, frame = cap.read() frame = cv.imread('imgs/30.png') # 没有视频,拿一张图片做一帧 # 转换颜色空间 BGR 到 HSV hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) # 定义HSV中蓝色的范围 lower_blue = np.array([110, 50, 50]) upper_blue = np.array([130, 255, 255]) # 设置HSV的阈值使得只取蓝色 mask = cv.inRange(hsv, lower_blue, upper_blue) # 将掩膜和图像逐像素相加 res = cv.bitwise_and(frame, frame, mask=mask) cv.imshow('frame', frame) cv.imshow('mask', mask) cv.imshow('res', res) k = cv.waitKey(5) & 0xFF if k == 27: break cv.destroyAllWindows()
效果图

如何获取 HSV像素值
如何获取 RGB空间 追踪像素的 HSV空间 对应的像素值 呢?
只需传递你想要的BGR值,而不是传递图像, 如
green = np.uint8([[[0, 255, 0]]]) hsv_green = cv.cvtColor(green, cv.COLOR_BGR2HSV) print(hsv_green) # [[[ 60 255 255]]] blue = np.uint8([[[255, 0, 0]]]) hsv_blue = cv.cvtColor(blue, cv.COLOR_BGR2HSV) print(hsv_blue) # [[[120 255 255]]]
然后把 [H-10, 100, 100] 和 [H+10, 255, 255] 分别作为下界和上界
除了这个方法之外,你可以使用任何图像编辑工具(如GIMP或任何在线转换器)来查找这些值,但是不要忘记调整HSV范围
参考资料:
https://baike.baidu.com/item/HSV/547122?fr=aladdin HSV颜色模型
http://www.woshicver.com/FifthSection/4_1_%E6%94%B9%E5%8F%98%E9%A2%9C%E8%89%B2%E7%A9%BA%E9%97%B4/ 中文官网
https://mp.weixin.qq.com/s/YvAhBsIT3qSSVh1Ue4UFrg 开始使用 OpenCV 进行对象跟踪
https://blog.csdn.net/Aoman_Hao/article/details/126295498?spm=1001.2014.3001.5502 色彩空间介绍
https://mp.weixin.qq.com/s/MnsRddkcVClFrBHcD0RMBQ

浙公网安备 33010602011771号