不同色彩转换

〇 引子

图像有多种色彩模型,如灰度图、RGB、HSV、YCbCr等等。这些图片文件在计算机中以不同的格式存在,如JPEG、png。图像的原始存储格式限定了读取到内存后的存在形式,在图像处理、计算机视觉中通常需要处理特定格式的图像,这就需要经常转换图像格式。
如对于彩色图像的直方图均衡需要图像的luma层,但大多图像为JPEG格式,只有R、G、B三个通道,在进行直方图均衡化之前需要转换为YCrCb格式。下图对比了对彩色图像R、G、B三个通道单独直方图均衡化(上)和对luma层直方图均衡化(下)的效果。

R、G、B三通道单独直方图均衡化,左为原图,右为效果图
luminance层直方图均衡化,左为原图,右为效果图

本文第一节将简单介绍常见的图像色彩空间,第二节介绍OpenCV文件读取、色彩模型转换,最后是直方图均衡化的应用case。

一 色彩模型

色彩模型、色彩空间和色彩系统是三个不同的概念。这三个概念往往会同时出现,经常彼此代替,理解其中的区别更利于以后的工作。
归根到底,色彩是人(动物)对光的感受,眼睛作为传感器接收外界的光波,传递给大脑,大脑反映出具体的色彩感受。所以对色彩的研究至少包括以下三个方面:

  • 真实世界的光波(波长、强度)
  • 眼睛(晶状体、视网膜、视神经细胞等)
  • 大脑(感觉)
不同色彩转换_第1张图片
可见光在光谱中的位置

灰度图

单通道图像。每个像素由一个8bit整数表示灰阶,像素值范围是[0, 255]0表示黑色, 255表示白色,中间值表示过渡。

不同色彩转换_第2张图片
灰度图(左),灰度图细节(中),灰度图的四个像素(右)

RGB

每个图像由R(red)、G(green)、B(blue)三个通道组成,一个像素点的像素值用一个三维向量表示[r, g, b]。向量中的每个分量表示在对应通道上的颜色值,也是8bit整数,范围是[0,255]。web前端和手机app开发的同学应该对这种色彩空间不会陌生。

不同色彩转换_第3张图片
RGB彩色图(左),彩色图细节(中),彩色图的四个像素(右)

HSV

H (Hue)是色调、色相。S(Saturation)是饱和度,V(Value)表示黑暗或明亮的程度。H色相是HSV中最重要的特征,简单讲,H决定了红、橙、黄、绿的特征。S饱和度又称为彩度、色彩浓度(chroma),从色彩最大到无色彩(黑/白/灰)的程度。

Y'CbCr

严格来说,这不是一种色彩模型,而是一种luma+chroma的编码方案。Y'CbCrYCbCr的概念也有一段历史。Y是颜色空间内的luminance 流明、亮度分量,Y'表示luma 亮度分量,这两个概念有差别。大部分时候,我们实际中用到的都是luma,所以很多库和程序中都按luma分量计算,不区分lumianceluma。如果你对Y luminanceY' luma的内容感兴趣,请阅读Understanding Luminance and Chrominance。CbCr分别是蓝色和红色的色彩偏移量。由于人眼对Y分量最敏感,因此基于JPEG格式的压缩技术通常压缩非Y分量。

这里只是略微讲了一下色彩模型和理论,强烈推荐UI 设计知识库 [01] 色彩 · 理论加强学习。

二 OpenCV

图像文件读取

import cv2
image = cv2.imread('./path/to/image', flag)

flag的方式读取image文件。flag包括以下几种常见值:

  • cv2.IMREAD_COLOR, 1, 默认值,返回BGR图像,会丢弃图像的透明通道。
  • cv2.IMREAD_GRAY,0, 灰度图。
  • cv2.IMREAD_UNCHANGED,-1,保持图像的透明通道。

在默认cv2.IMREAD_COLOR方式下,返回的图像是BGR图像注意区分OpenCV返回的不是RGB图像,通道顺序相反。即使是灰度图,也会返回BRG格式。在施加变换的时候就要特别注意通道顺序。

BGR图像的三个通道像素值大多采用[0, 255]的范围,但也有在[0, 65535]或者[0, 1]。值域范围对线性变化没有任何影响,但是如果对图像进行非线性变换就要特别注意,例如BGR图像到LUV图像的变换。

彩色空间转化

OpenCV中转化图像格式使用cvtColor(img, flag),下面的代码演示了转换BGR图像到HSV图像的过程。

import cv2
img_bgr = cv2.imread('lena.jpg') # 默认BGR
# convert BGR image to HSV image
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)

方法很简单,重点是你要清醒地知道你需要什么样的图像格式才能完成转化。OpenCV中提供了数百种图像彩色空间的转换方法,也就是flag有数百种选择,下面代码会输出所有支持的参数:

import cv2
flags = [ flag for flag in dir(cv2) if flag.startswith('COLOR_') ]
for flag in flags:
    print('flag: cv2.{0}, value = {1}'.format(flag, eval('cv2.'+flag)))

执行上面代码会输出258种参数(OpenCV 3.1.0),部分截图如下:

不同色彩转换_第4张图片
颜色空间转换可选参数

是不是被这么多的方法吓到了?如果直接输出上面参数的值,你会发现一些参数是相等的,例如cv2.COLOR_BGR2YCR_CBcv2.COLOR_BGR2CrCb都是36,因为这两种方法是一样的,这样的设计应该只是为了输入方便而已【微笑】。

具体的转换公式需要更多专业的图像处理知识,OpenCV说明文档给出了一些简单的说明可供参考。

BGR和YCrCb色彩空间转换

OpenCV中BGRYCrCb的色彩空间转换公式:

RGB to Y

RGB to Cr
RGB to Cb

公式中的delta值:

delta值

维基百科中JPEG转化公式:

BGR to Y'CrCb

可以看出OpenCV中的Y即维基百科中的Y'

下面的代码片段演示了如何分理彩色图像的Y通道:

import cv2
img_bgr = cv2.imread('./deer.jpg', cv2.IMREAD_COLOR)
img_ycrcb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YCrCb)
y, cr, cb = cv2.split(img_ycrcb)
cv2.imwrite('./deer_y.jpg')
cv2.imshow('y', y)
cv2.waitKey()
cv2.destroyAllWindows()
不同色彩转换_第5张图片
rgb image
不同色彩转换_第6张图片
y component of ycrcb image

三 彩色图像直方图均衡化

对彩色图像的直方图均衡化步骤如下:

  1. 读取彩色图像,得到BGR格式的图像矩阵
  2. 转化色彩空间,BGR 到 YCrCb
  3. 分离(split)YCrCb图像中的Y分量,直方图均衡化
  4. 合并(merge)Y分量和Cr、Cb分量,得到直方图均衡化后的YCrCb格式的图像矩阵
  5. 转化YCrCb格式到BGR格式并保存
import cv2

img = cv2.imread('./deer.jpg', cv2.IMREAD_COLOR)
# 单独对B、G、R三个通道进行直方图均衡化
b, g, r = cv2.split(img)
b_eqhist = cv2.equalizeHist(b)
g_eqhist = cv2.equalizeHist(g)
r_eqhist = cv2.equalizeHist(r)
img_eqhist_bgr = cv2.merge([b_eqhist, g_eqhist, r_eqhist])
cv2.imwrite('deer_eq_bgr.jpg', img_eqhist_bgr)

# 转换到YCrCb色彩空间,对Y分量进行直方图均衡化
img_ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
y, cr, cb = cv2.split(img_ycrcb)
y = cv2.equalizeHist(y)
img_ycrcb = cv2.merge([y, cr, cb])
img = cv2.cvtColor(img_ycrcb, cv2.COLOR_YCrCb2BGR)
cv2.imwrite('deer_eq.jpg', img)
不同色彩转换_第7张图片
单独对BGR三个通道进行直方图均衡化效果
不同色彩转换_第8张图片
YCrCb色彩空间直方图均衡化效果
不同色彩转换_第9张图片
原图

参考

  1. Lectures on Image Processing by Alan Peters
  2. OpenCV图像变换
  3. WIKI YCbCr
  4. 百度百科 YCbCr
  5. Understanding Luminance and Chrominance
  6. UI 设计知识库 [01] 色彩 · 理论

你可能感兴趣的:(不同色彩转换)