OpenCV的颜色空间(cv2.cvtColor)
Posted 程序媛一枚~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV的颜色空间(cv2.cvtColor)相关的知识,希望对你有一定的参考价值。
OpenCV的颜色空间(cv2.cvtColor)
这篇博客将介绍OpenCV中的3种颜色空间(RGB、HSV、 Lab)及其转换,并讨论光照条件、色彩空间在计算机视觉应用中的关键作用。
关键要点是在编写代码前始终考虑照明条件!一般来说,控制照明条件比编写代码来补偿在低质量下捕获的图像更容易。
- RGB颜色空间是计算机视觉中最常见的颜色空间,简单但并不直观,因为很难肉眼准确确定某种颜色由多少红色、绿色和蓝色组成。呈现为立方体。
- HSV 颜色空间很直观,它允许沿着圆柱体而不是 RGB 立方体定义颜色。 HSV 颜色空间还为亮度/白度提供了单独的维度,从而更容易定义颜色深浅。
- RGB 和 HSV 都无法模仿人类感知颜色的方式,而 Lab 色彩空间可以感知差异,并从欧几里得距离判断俩种颜色的相似性。
1. 效果图
RGB原图 VS 各通道效果图如下:
HSV原图 VS 各通道效果图如下:
Value 图本质上是一个灰度图像——这是因为该值控制着颜色的实际亮度,而 Hue 和 Saturation 定义了实际的颜色和阴影。
Lab VS 各通道效果图如下:
与HSV示例类似,L通道专门用于显示给定像素的亮度。 a通道和b通道确定了像素的阴影和颜色。
2. 原理
2.1 照明条件的重要性
照明可能意味着计算机视觉算法成功与失败之间的区别。事实上,光照甚至可能是最重要的因素。
在编写代码之前,尽可能地获得理想的照明条件。控制照明条件比编写代码来补偿较低的照明条件更容易。
处理光照条件时应寻求实现的三个目标:
-
高对比度(应该寻求最大化图像中感兴趣区域之间的对比度(即想要检测、提取、描述、分类、操作等的“对象”与图像的其余部分具有足够高的对比度,尽量确保环境的背景和前景之间有高对比度);
-
可推广的(照明条件应该足够一致,以便扩展);
-
稳定的(具有稳定、一致、可重复的光照条件是计算机视觉应用开发的圣杯。)
2.2 OpenCV 中的3种颜色空间/模型
颜色模型是在颜色空间中用数字表示颜色的一种抽象方法。
- RGB
RGB 代表图像中的红、绿、蓝分量,通常被视为立方体。
- RGB颜色空间是加法颜色空间的一个示例:添加的颜色越多,像素越亮,越接近白色;
- [0,255]共256个值; 红色+绿色=黄色。红色+蓝色=粉红色。红+绿+蓝=白色。
R=252, G=198, B=188 = 白色人种肤色。
R=22,G=159,B=230=蓝色徽标。
- HSV
HSV 颜色空间将其重塑为圆柱体而不是立方体,亮度是一个单独的维度
- Hue:色调,正在检查哪种“纯”颜色。例如“红色”颜色的所有阴影和色调都将具有相同的色调。 [0, 179]
- Saturation:饱和度,颜色有多“白”。完全饱和的颜色将是“纯色”,如“纯红色”。零饱和度的颜色将是纯白色。 [0, 255]
- Value:值允许控制颜色的亮度。值为零表示纯黑色,而增加值会产生较浅的颜色。 [0, 255]
- Lab
在RGB 和 HSV 颜色空间中,欧几里得距离无法“测量”各种颜色之间颜色的感知差异。 而Lab 颜色空间可以模仿人类观察和解释颜色的方法。 Lab 是一个3轴系统,它使得两种任意颜色之间的欧几里德距离具有实际的感知意义。**
- L-通道:像素的“亮度”。该值在垂直轴上上下变化,从白色到黑色,在轴的中心为中性灰色。
- a-通道:源自 L 通道的中心,在光谱的一端定义纯绿色,在另一端定义纯红色。
- b 通道:源自 L 通道的中心,但垂直于 a 通道。 b 通道在光谱中一端定义纯蓝色,另一端定义纯黄色。 同样,虽然 Lab* 颜色空间不如 HSV 和 RGB 颜色空间直观且不易理解,但它在计算机视觉中得到了大量使用。
这是由于颜色之间的距离具有实际的感知意义,使我们能够克服各种光照条件问题。它还用作强大的彩色图像描述符。
2.3 颜色空间的主要用途
-
RGB:足够简单,主要用于在显示器上显示颜色;
-
HSV:当有兴趣根据颜色跟踪图像中的对象时,使用 HSV 定义颜色范围非常容易。
-
Lab:提供了感知均匀性,可以模仿人类观察和解释颜色的方法,使得两种任意颜色之间的距离具有实际意义。 当关心跨多个设备的色彩管理、色彩传输或色彩一致性时,L * a * b色彩空间可以提供出色的彩色图像描述符。
-
灰度:不是颜色空间,但在颜色无关紧要的应用中,例如在检测人脸或构建对象分类器时,忽略颜色使用图像的灰度表示——这能够节省内存并提高计算效率。
3. 源码
# 加载图像,并演示如何使用RGB、HSV和L*a*b*颜色空间。
# USAGE
# python color_spaces.py
# 导入必要的包
import argparse
import cv2
import imutils
# 构建命令行参水及解析
# --image 输入图像路径
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str, default="ml3.jpg",
help="path to input image")
args = vars(ap.parse_args())
# 加载图像并展示
image = cv2.imread(args["image"])
image = imutils.resize(image, width=200)
cv2.imshow("RGB", image)
# 遍历每一个单独的通道并展示
# RGB 是最常用的色彩空间,但它并不是最直观的色彩空间。
# 颜色的“白色”或“亮度”是每个红色、绿色和蓝色分量的加法组合。
for (name, chan) in zip(("B", "G", "R"), cv2.split(image)):
cv2.imshow(name, chan)
# 等待按键,关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
# HSV 颜色空间转换 RGB 颜色空间,将其重塑为圆柱体而不是立方体,亮度是一个单独的维度
# - Hue:色调,正在检查哪种“纯”颜色。例如“红色”颜色的所有阴影和色调都将具有相同的色调。 [0, 179]
# - Saturation:饱和度,颜色有多“白”。完全饱和的颜色将是“纯色”,如“纯红色”。零饱和度的颜色将是纯白色。 [0, 255]
# - Value:值允许控制颜色的亮度。值为零表示纯黑色,而增加值会产生较浅的颜色。 [0, 255]
# 转换图像为HSV颜色空间并展示
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
cv2.imshow("HSV", hsv)
# 遍历每一个单独的H、S、V通道并展示
for (name, chan) in zip(("H", "S", "V"), cv2.split(hsv)):
cv2.imshow(name, chan)
# 按键关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
# L * a * b颜色空间
# 计算红色和绿色之间的欧几里德距离;红色和紫色;以及 RGB 颜色空间中的红色和海军蓝:
import math
red_green = math.sqrt(((255 - 0) ** 2) + ((0 - 255) ** 2) + ((0 - 0) ** 2))
red_purple = math.sqrt(((255 - 128) ** 2) + ((0 - 0) ** 2) + ((0 - 128) ** 2))
red_navy = math.sqrt(((255 - 0) ** 2) + ((0 - 0) ** 2) + ((0 - 128) ** 2))
print(red_green, red_purple, red_navy)
# 在RGB、HSV颜色空间计算欧几里得距离,并不能得出红色在某种意义上更类似于紫色而不是绿色?,
# 欧几里得距离无法“测量”各种颜色之间颜色的感知差异在 RGB 和 HSV 颜色空间中。
# 这就是 L*a*b* 颜色空间的用武之地——它的目标是模仿人类观察和解释颜色的方法。
# L*a*b* 颜色空间中两种任意颜色之间的欧几里德距离具有实际的感知意义。
# 感知意义的加入使得 L*a*b* 颜色空间不如 RGB 和 HSV 那样直观和理解,但它在计算机视觉中被大量使用。本质上,L*a*b* 颜色空间是一个 3 轴系统:
# - L-通道:像素的“亮度”。该值在垂直轴上上下变化,从白色到黑色,在轴的中心为中性灰色。
# - a-通道:源自 L 通道的中心,在光谱的一端定义纯绿色,在另一端定义纯红色。
# - b 通道:也源自 L 通道的中心,但垂直于 a 通道。 b 通道在光谱中一端定义纯蓝色,另一端定义纯黄色。
# 同样,虽然 L*a*b* 颜色空间不如 HSV 和 RGB 颜色空间直观且不易理解,但它在计算机视觉中得到了大量使用。
# 这是由于颜色之间的距离具有实际的感知意义,使我们能够克服各种光照条件问题。它还用作强大的彩色图像描述符。
# 转换图像为L*a*b空间并展示
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
cv2.imshow("L*a*b*", lab)
# 遍历每个通道并展示
for (name, chan) in zip(("L*", "a*", "b*"), cv2.split(lab)):
cv2.imshow(name, chan)
# 等待按键,关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
# 展示灰度图,灰度图并不是一种颜色空间
# 鉴于眼睛对色彩的敏感程度,眼睛的受体和锥体不同,因此比蓝色更能感知绿色和红色。感知绿色的量是红色的近2被,感知红色的量是蓝色的俩倍多,
# 因此在转换为灰度时,每个 RGB 通道的权重不均匀,
# Y = 0.299 \\times R + 0.587 \\times G + 0.114 \\times B
# 当颜色无关紧要时,通常使用图像的灰度表示(例如在检测人脸或构建对象分类器时,对象的颜色无关紧要)。因此丢弃颜色能够节省内存并提高计算效率。
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Original", image)
cv2.imshow("Grayscale", gray)
cv2.waitKey(0)
参考
以上是关于OpenCV的颜色空间(cv2.cvtColor)的主要内容,如果未能解决你的问题,请参考以下文章