不同色彩转换

〇 引子

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

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

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

一 色彩模型

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

  • 真实世界的光波(波长、强度)
  • 眼睛(晶状体、视网膜、视神经细胞等)
  • 大脑(感觉)
可见光在光谱中的位置

灰度图

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

灰度图(左),灰度图细节(中),灰度图的四个像素(右)

RGB

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

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 ChrominanceCbCr分别是蓝色和红色的色彩偏移量。由于人眼对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),部分截图如下:

颜色空间转换可选参数

是不是被这么多的方法吓到了?如果直接输出上面参数的值,你会发现一些参数是相等的,例如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()
rgb image
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)
单独对BGR三个通道进行直方图均衡化效果
YCrCb色彩空间直方图均衡化效果
原图

参考

  1. Lectures on Image Processing by Alan Peters
  2. OpenCV图像变换
  3. WIKI YCbCr
  4. 百度百科 YCbCr
  5. Understanding Luminance and Chrominance
  6. UI 设计知识库 [01] 色彩 · 理论
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容