在图像处理中,颜色转换是常见模块。为什么要用上颜色转换呢?因为我们拍摄的图像通常是RGB格式的,五颜六色。这种颜色对计算机是好识别的,但是对人的肉眼不友好,因为人的肉眼对红色等很多颜色不敏感。这样我们就需要RGB格式转换为HSV,HSL,YUV颜色模型进行处理。

也就是说:RGB图像与相机传感器输出的原始数据相对应,HSV图像则与我们人类的直观视觉更相符。

 

RGB

RGB 代表红绿蓝(Red, Green, Blue)

在 RGB 模型中,颜色由不同强度的红色、绿色和蓝色光的组合来创建。这三种基本颜色的不同组合产生了各种颜色。

在 RGB 模型中,每个颜色通道的强度通常以数字值表示,取值范围为 0 到 255,其中 0 表示没有该颜色的强度,255 表示该颜色通道的最大强度。

例如,RGB 代码 RGB(255, 0, 0) 表示纯红色,其中:

  • 255 表示红色通道的强度为最大(红色)。
  • 0 表示绿色通道的强度为零(没有绿色)。
  • 0 表示蓝色通道的强度为零(没有蓝色)。

这样对比地引出了HSV颜色模型

HSV

HSV 代表色相(Hue)、饱和度(Saturation)和明度(Value)。 这个模型是通过人类对颜色的感知方式设计的,更符合人们对颜色的主观感受。

以下是HSV 模型的三个组成部分:

  • H(色相 - Hue): 表示颜色的种类,它是一个在0到360度之间的角度值。色相值对应于光谱上的不同颜色,比如红色、绿色、蓝色等。

  • S(饱和度 - Saturation): 表示颜色的纯度或强度。饱和度为0表示灰度,即一种无色。饱和度为100%表示颜色是纯净的,没有被白色或其他颜色混合。也就是说 S 控制纯色中混入白色的量,值越大,白色越少,颜色越纯;

  • V(明度 - Value): 表示颜色的亮度。明度为0表示黑色,明度为100%表示白色。。也就是说V 控制纯色中混入黑色的量,值越大,黑色越少,明度越高

HSV 模型的优势在于它更符合人们对颜色的感知

HSV 和 HSL 在字面意思上是一样的:

  • H 指的是色相(Hue),就是颜色名称,例如“红色”、“蓝色”;
  • S 指的是饱和度(Saturation),即颜色的纯度;
  • L(Lightness) 和 V(Value)是明度,颜色的明亮程度

在原理和表现上,HSL 和 HSB 中的 H(色相) 完全一致,但二者的 S(饱和度)不一样, L 和 B (明度 )也不一样:

  • HSV 中的 S 控制纯色中混入白色的量,值越大,白色越少,颜色越纯;
  • HSV 中的 V 控制纯色中混入黑色的量,值越大,黑色越少,明度越高
  • HSL 中的 S 和黑白没有关系,饱和度不控制颜色中混入黑白的多寡;
  • HSL 中的 L 控制纯色中的混入的黑白两种颜色。

 

Opencv提供了cvtColor函数,调用该函数可以非常方便地实现不同颜色空间的转换。不过为了可视化,调用该函数得到的HSV图像,其H、S、V三通道的取值范围是经过转换的0~180、0~255、0~255。

import cv2 as cv
cv.cvtColor(src, code[,dst[,dstCn]])

  其中,src代表原图像,code表示转换的类型。例如:对于BGR→HSV,我们使用标志cv.COLOR_BGR2HSV。

举例:

img = cv2.imread("./images/test.jpg")
# 换到 HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

RGB到HSV的转换是如何进行的?

RGB到HSV的转换使用数学计算进行。

  1. 首先,将RGB值标准化,即将每个成分的值转换为0到1的范围。
  2. 然后找到最小值(R、G、B中的最小值)和最大值(R、G、B中的最大值)。
  3. 计算色相(Hue)。如果最大值等于最小值,则色相为0。
  4. 计算饱和度(Saturation)。饱和度计算为(max-min)/max。
  5. 计算明度(Value)。明度与最大值相同。

比如

RGB是(255,0,0)的最小值是0,最大值是255, 在R通道,以最大值为准,H色度为红色,S饱和度 (255-0)/255=1 ,没有混入白色。明度是255,最大,故按比例缩放是1,没有混入黑色。所以是纯红。再按照比例转成hsv 模型,如下图的六角锥形。可见红色是0度。进一步地,再转换为0~180、0~255、0~255范围

 

注意:

  1. 从一个色彩空间转换到另一个色彩空间,信息传递会损失;
  2. HSV的色相范围为[0,179],饱和度范围为[0,255],值范围为[0,255]。
  3. 色彩空间转换可能可逆,也可能不可逆。A转成了B.B再转成A,可能可以回到原图,可能无法回到原图。比如BRG转成HSV,再转回BRG,可以回到原图。
import cv2 as cv

def reversible_demo():
  img = cv.imread('./images/butterfly.jpg')
  cv.imshow('Original Image', img)
  hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
  cv.imshow('BGR2HSV Image', hsv)
  # 逆转原图
  hsv2bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
  cv.imshow('HSV2BGR Image', hsv2bgr)
  cv.waitKey(0)
  cv.destroyAllWindows()

if __name__ == "__main__":
  reversible_demo()

  可逆

 BGR转成GRAY 类型(GRAY色彩空间:GRAY(灰度图像)通常指8位灰度图,其具有256个灰度级,像素值的 范围是[0,255]。)再转回BGR类型

import cv2 as cv

def irreversible_demo():
  img = cv.imread('./images/butterfly.jpg')
  cv.imshow('Original Image', img)
  gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
  cv.imshow('BGR2GRAY Image', gray)
  # 逆转原图
  gray2bgr = cv.cvtColor(gray, cv.COLOR_GRAY2BGR)
  cv.imshow('GRAY2BGR Image', gray2bgr)
  cv.waitKey(0)
  cv.destroyAllWindows()

if __name__ == "__main__":
  irreversible_demo()

  不可逆

实际案例分析

将一个红色的密封圈实物特征提取出来。根据下图模块流程。

注意读取源图像时需选择RGB格式

 

不能选择MONO8格式,MONO8格式为灰度图。

 我们发现改成RGB格式,模块就变绿了,没报错。报错原因就是选择的图像的格式不对。

 接着,二值化把HSV图像的第一通道的阈值在245-255,即红色(红色的色度范围是0-10,或者156-180)的特征----图像特征提取出来

 

 目前存疑的是,红色的色度为156-180,因为色度范围是0-180.转为二值化阈值应该按照比例换算过来。阈值范围是0-255。所以二值化阈值应该不是156-180.应该是245-255

 怎么样才是准确地提取红色的实物?