OpenCV 笔记(21):图像色彩空间

1. 图像色彩空间

图像色彩空间是用于定义颜色范围的数学模型。

它规定了图像中可以使用的颜色以及它们之间的关系。它决定了图像中可以显示的颜色范围。不同的色彩空间可以包含不同的颜色范围,因此选择合适的色彩空间对于确保图像在不同设备上看起来一致非常重要。

图像色彩空间的意义主要体现在以下几个方面:

  • 统一颜色标准:色彩空间提供了一种统一的颜色标准,使得不同设备之间能够相互理解和交流颜色信息。
  • 确保颜色一致性:色彩空间可以确保图像在不同设备上显示时颜色一致。
  • 提高图像质量:色彩空间可以提高图像质量。
  • 简化图像处理:色彩空间可以简化图像处理过程,提高图像处理效率。
  • 促进色彩管理:色彩空间是色彩管理的基础。色彩管理是指确保图像在不同设备上显示时颜色一致的过程。通过使用色彩空间,我们可以将图像转换为与目标设备的色彩空间相匹配的色彩空间,从而确保图像在不同设备上显示时颜色一致。

2. 最常见的图像色彩空间

2.1 RGB

RGB 色彩空间是一种基于红、绿、蓝三原色的加色色彩空间。它是用于显示器和电视机的颜色空间,也是用于大多数数字图像的色彩空间。

RGB 色彩空间使用三个分量来表示颜色:红色、绿色和蓝色。每个分量都是一个介于 0 到 255 之间的数字,其中 0 表示该原色不存在,255 表示该原色完全存在。通过混合不同强度的红、绿、蓝光,可以创建各种颜色。例如,混合相等强度的红、绿和蓝光会产生白色光。混合全强度红色和全强度绿色会产生黄色光。

RGB图1.png
RGB图2.png

RGB 色彩空间根据每个分量在计算机中占用的存储字节数的几种常见情况:

  • RGB24: 每个分量占用8位,共24位,是最常见的RGB格式。
  • RGB565: R分量占用5位,G分量占用6位,B分量占用5位,共16位。这种格式可以节省存储空间,但颜色精度较低。
  • RGB555: R分量、G分量和B分量各占用5位,共15位。这种格式与RGB565类似,但颜色精度更低。
  • RGB32: 每个分量占用8位,共32位。增加了透明度通道,可以用于表示透明图像。这种格式可以提供更高的颜色精度,但需要更多的存储空间。

2.2 HSV

HSV 色彩空间是一种使用色相、饱和度和值来表示颜色的色彩空间。它是一种直观的色彩空间,与人眼感知颜色的方式更加接近。

HSV 色彩空间的三个分量:

  • 色相 (Hue):指的是颜色的基本属性,例如红色、黄色、绿色等。色相通常用角度来表示,范围为0-360度。
  • 饱和度 (Saturation):指的是颜色的纯度,也就是颜色中灰色成分的多少。饱和度越高,颜色越纯净;饱和度越低,颜色越灰暗。饱和度通常用百分比来表示,范围为0-100%。
  • (Value):指的是颜色的亮度,也就是颜色的明暗程度。值越高,颜色越明亮;值越低,颜色越暗淡。值通常用百分比来表示,范围为0-100%。

HSV 是一种将 RGB 色彩空间中的点在倒圆锥体中的表示方法。360度的圆作为色相,饱和度的值就是色相切点指向圆心的线,此时的颜色还是不够用于表示。再引入一个亮度,圆锥的垂线,越往上图片越亮,反之越暗。

HSV图1.png
HSV图2.png

HSV 色彩空间主要应用在以下几个方面:

  • 图像分割:可以根据颜色范围来提取图像中的特定对象。
  • 颜色校正:可以调整图像的饱和度或明度来改善图像质量。
  • 特效处理:可以改变图像的颜色或创建特殊效果。
  • 计算机图形: 可以用于创建逼真的物体和场景。

HSV 颜色对应 RGB 分量范围(通过实验计算的模糊范围)

hsv 对应的 rgb 分量范围.png

2.3 HLS

HLS 色彩空间是一种使用色相、饱和度和明度来表示颜色的色彩空间。

HLS 色彩空间的三个分量:

  • 色相 (Hue): 色相是指颜色的基本属性,通常用角度来表示,范围为0°到360°。0°代表红色,120°代表绿色,240°代表蓝色,360°又回到红色。
  • 饱和度 (Saturation): 饱和度是指颜色的纯度,取值范围为0%到100%。0%表示灰色,100%表示完全饱和。
  • 明度 (Lightness): 明度是指颜色的亮度,取值范围为0%到100%。0%表示黑色,100%表示白色。
HLS.png

下面整理了 HLS 和 HSV 色彩空间的区别:

特性 HLS HSV
色相 相同 相同
饱和度 颜色与同亮度、无彩色(灰色)的最大差异程度 颜色纯度
亮度 感知到的明暗程度 颜色的明度
几何形状 双圆锥体和圆球体 倒圆锥体
适用范围 图形设计、用户界面 图像处理、计算机图形
HLS和HSV对比.png

2.4 YUV

YUV 色彩空间是一种使用亮度(Y)和两个色度分量(U和V)来表示颜色的颜色空间。它主要用于电视和视频领域。

YUV 色彩空间的三个分量:

  • Y:代表亮度,也就是灰度值。
  • U:代表蓝色和黄色之间的色度分量。
  • V:代表红色和青色之间的色度分量。
YUV.png

由上图可知,亮度和颜色无关只是黑白灰的程度不同,因此 UV 信息代表颜色。

YUV 色彩空间的常见格式:

  • YUV420:一种常见的 YUV 格式,每个像素占用 1.5 个字节。其中 Y 分量占用 1 个字节,U 和 V 分量各占用 0.25 个字节。
  • YUV422:另一种常见的 YUV 格式,每个像素占用 2 个字节。其中 Y 分量占用 1 个字节,U 和 V 分量各占用 0.5 个字节。
  • YUV444: 每个像素占用 3 个字节,其中 Y、U 和 V 分量各占用 1 个字节。这种格式提供最高的图像质量,但需要最多的存储空间。

YUV 色彩空间常见格式:

格式 Y U V 存储空间 图像质量
YUV444 8位 8位 8位 24位 最高
YUV422 8位 8位 (每隔一个像素采样) 8位 (每隔一个像素采样) 16位 中等
YUV420 8位 4位 (每隔两个像素采样) 4位 (每隔两个像素采样) 12位 较低

另外,还有 YCbCr,YCbCr 是从 YUV 色彩空间派生而来,但 YCbCr 采用了更复杂的数学公式,以便更好地利用人眼的视觉特性。

2.5 CMY & CMYK

CMY 色彩空间是一种基于减色原理的颜色空间,使用青色 (Cyan)、品红 (Magenta) 和黄色 (Yellow) 三原色来表示颜色。它通常用于印刷和出版领域,因为CMY油墨可以很好地吸收光线,从而产生各种各样的颜色。

CMY.png

CMY 色彩空间的工作原理:白色光包含所有可见光谱。当白色光穿过 CMY 油墨时,油墨会吸收部分光谱。未被吸收的光线会反射到我们的眼睛中,我们看到的就是 CMY 颜色。

CMYK 是 CMY 的扩展增加了黑色分量。这是因为 CMY 无法完美地再现黑色,因此添加黑色分量可以提高阴影和暗调的准确性。

CMY 和 CMYK 色彩空间的比较:

特性 CMY CMYK
颜色分量 青色、品红、黄色 青色、品红、黄色、黑色
颜色模式 减色 减色
适用范围 印刷 印刷
黑色分量
色彩范围 较小 较大
印刷成本 较低 较高

2.6 Lab

Lab 色彩空间 是一种基于人眼感知的色彩空间,比其他颜色空间(如 RGB 和 CMYK)更接近于感知颜色。

Lab 色彩空间的三个分量:

  • L:代表亮度,取值范围为 0-100,0 表示黑色,100 表示白色。
  • a:代表从红色到绿色的范围,取值范围为 -128 到 127,-128 表示绿色,127 表示红色。
  • b:代表从蓝色到黄色的范围,取值范围为 -128 到 127,-128 表示蓝色,127 表示黄色。

Lab 色彩空间的特性:

  • 感知均匀性好:Lab 色彩空间与人眼感知颜色方式更接近,因此具有较好的感知均匀性。
  • 颜色范围大:Lab 色彩空间可以表示比 RGB 和 CMYK 更广泛的颜色范围。
  • 与设备无关:Lab 色彩空间与设备无关,因此可以在不同的设备之间准确地转换颜色。
Lab.png

3. 图像色彩空间转换

图像色彩空间转换是指将图像从一个色彩空间转换到另一个色彩空间的过程。

OpenCV 提供了 cv::cvtColor() 函数进行图像色彩空间转换,常见的转换方法:

  • RGB 到 HSV:
cv::cvtColor(src, dst, cv::COLOR_RGB2HSV);
  • HSV 到 RGB:
cv::cvtColor(src, dst, cv::COLOR_HSV2RGB);
  • RGB 到 YUV:
cv::cvtColor(src, dst, cv::COLOR_RGB2YUV);
  • YUV 到 RGB:
cv::cvtColor(src, dst, cv::COLOR_YUV2RGB);
  • RGB 到 Lab:
cv::cvtColor(src, dst, cv::COLOR_RGB2Lab);
  • Lab 到 RGB:
cv::cvtColor(src, dst, cv::COLOR_Lab2RGB);

下面的例子,展示了在 OpenCV 中使用 cvtColor()函数将原图转换到各种色彩空间。

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char **argv) {
    Mat src = imread(".../flower.jpg");
    imshow("src", src);

    Mat gray;
    cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    imshow("gray", gray);

    Mat hsv;
    cvtColor(src, hsv, cv::COLOR_BGR2HSV); // BGR 转换到 HSV 色彩空间
    imshow("hsv", hsv);

    Mat hls;
    cvtColor(src, hls, cv::COLOR_BGR2HLS); // BGR 转换到 HLS 色彩空间
    imshow("hls", hls);

    Mat yuv;
    cvtColor(src, yuv, cv::COLOR_RGB2YUV); // BGR 转换到 YUV 色彩空间
    imshow("yuv", yuv);

    Mat lab;
    cvtColor(src, lab, cv::COLOR_RGB2Lab); // BGR 转换到 Lab 色彩空间
    imshow("lab", lab);

    waitKey(0);
    return 0;
}
原图和灰度图.png
hsv和hls色彩空间.png
yuv和lab色彩空间.png

4. 颜色分割

下面的例子,先将图片转换到 HSV 色彩空间,再通过 cv::inRange() 函数将女孩从绿色背景分离出来,最后用蓝色背景替换原先的绿色背景。

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char **argv) {
    Mat src = imread(".../girl.jpg");
    imshow("src", src);

    Mat hsv;
    cvtColor(src, hsv, cv::COLOR_BGR2HSV); // BGR 转换到 HSV 色彩空间
    imshow("hsv", hsv);

    cv::Scalar lower_green(35, 43, 46);
    cv::Scalar upper_green(77, 255, 255); // 定义绿色的 HSV 范围

    Mat mask;
    inRange(hsv, lower_green, upper_green, mask); // 通过 inRange 函数实现二值化
    imshow("mask", mask);

    Mat kernel = getStructuringElement(MORPH_RECT,Size(7,7),Point(-1,-1));
    morphologyEx(mask, mask, MORPH_OPEN, kernel, Point(-1, -1), 1);
    imshow("open", mask);
    GaussianBlur(mask,mask,Size(45,45),0,0);
    imshow("blur", mask);

    bitwise_not(mask,mask);
    imshow("fg", mask);

    // 重新定义背景颜色
    Vec3b color;
    color[0] = 255;
    color[1] = 0;
    color[2] = 0;

    int height = src.rows;
    int width = src.cols;
    Mat result(src.size(),src.type());

    double w = 0.0;
    int b = 0,g = 0, r = 0;
    int b1 = 0,g1 = 0, r1 = 0;
    int b2 = 0,g2 = 0, r2 = 0;

    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            int m = mask.at<uchar>(row,col);
            if(m == 255){ //前景
                result.at<Vec3b>(row,col) = src.at<Vec3b>(row,col);
            } else if(m==0){ //背景
                result.at<Vec3b>(row,col) = color;
            } else{
                w = m/ 255;
                b1 = src.at<Vec3b>(row,col)[0];//前景
                g1 = src.at<Vec3b>(row,col)[1];
                r1 = src.at<Vec3b>(row,col)[2];

                b2 = color[0];//背景
                g2 = color[1];
                r2 = color[2];

                b = b1*w+b2*(1.0-w);
                g = g1*w+g2*(1.0-w);
                r = r1*w+r2*(1.0-w);

                result.at<Vec3b>(row,col)[0] = b;
                result.at<Vec3b>(row,col)[1] = g;
                result.at<Vec3b>(row,col)[2] = r;
            }
        }
    }

    imshow("result",result);

    waitKey(0);
    return 0;
}
原图以及转换到hsv.png
生成mask和形态学开操作.png
高斯模糊和bitwise_not操作.png
替换背景.png

下面简单介绍一下 cv::inRange() 函数:

void inRange(InputArray src, InputArray lowerb,
                          InputArray upperb, OutputArray dst);

第一个参数 src: 输入图像,可以是单通道或多通道图像。
第二个参数 lowerb: 颜色范围的下限,可以是标量或数组。
第三个参数 upperb: 颜色范围的上限,可以是标量或数组。
第四个参数 dst: 输出图像,与输入图像大小相同,类型为 CV_8U。

对于图像中的每个像素,cv::inRange() 函数会将其与 lowerb 和 upperb 进行比较。如果像素值在两者之间,则输出图像中的对应像素设置为 255,否则设置为 0。所以,实现了图像的二值化。

5. 总结

图像色彩空间在图像处理和显示中起着重要的作用。

除了本文介绍的图像色彩空间之外,还有许多其他图像色彩空间,每种色彩空间都有自己的优势和劣势。

图像色彩空间可以确保颜色一致性、提高图像质量、简化图像处理并促进色彩管理。随着技术的不断发展,图像色彩空间也在不断发展。

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

推荐阅读更多精彩内容