1. 图画颜色空间

图画颜色空间是用于界说颜色规模的数学模型。

它规则了图画中能够运用的颜色以及它们之间的联系。它决定了图画中能够显现的颜色规模。不同的颜色空间能够包含不同的颜色规模,因而选择适宜的颜色空间关于保证图画在不同设备上看起来共同非常重要。

图画颜色空间的意义首要体现在以下几个方面:

  • 统一颜色规范:颜色空间供给了一种统一的颜色规范,使得不同设备之间能够相互理解和交流颜色信息。
  • 保证颜色共同性:颜色空间能够保证图画在不同设备上显现时颜色共同。
  • 进步图画质量:颜色空间能够进步图画质量。
  • 简化图画处理:颜色空间能够简化图画处理进程,进步图画处理功率。
  • 促进颜色办理:颜色空间是颜色办理的根底。颜色办理是指保证图画在不同设备上显现时颜色共同的进程。经过运用颜色空间,咱们能够将图画转化为与目标设备的颜色空间相匹配的颜色空间,然后保证图画在不同设备上显现时颜色共同。

2. 最常见的图画颜色空间

2.1 RGB

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

RGB 颜色空间运用三个重量来表明颜色:赤色、绿色和蓝色。每个重量都是一个介于 0 到 255 之间的数字,其间 0 表明该原色不存在,255 表明该原色彻底存在。经过混合不同强度的红、绿、蓝光,能够创立各种颜色。例如,混合相等强度的红、绿和蓝光会发生白色光。混合全强度赤色和全强度绿色会发生黄色光。

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

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度的圆作为色相,饱和度的值便是色相切点指向圆心的线,此刻的颜色还是不行用于表明。再引入一个亮度,圆锥的垂线,越往上图片越亮,反之越暗。

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

HSV 颜色空间首要应用在以下几个方面:

  • 图画分割:能够依据颜色规模来提取图画中的特定目标。
  • 颜色校对:能够调整图画的饱和度或明度来改善图画质量。
  • 特效处理:能够改动图画的颜色或创立特殊效果。
  • 计算机图形: 能够用于创立传神的物体和场景。

HSV 颜色对应 RGB 重量规模(经过试验计算的模糊规模)

OpenCV 笔记(21):图画颜色空间

2.3 HLS

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

HLS 颜色空间的三个重量:

  • 色相 (Hue): 色相是指颜色的根本属性,通常用视点来表明,规模为0到360。0代表赤色,120代表绿色,240代表蓝色,360又回到赤色。
  • 饱和度 (Saturation): 饱和度是指颜色的纯度,取值规模为0%到100%。0%表明灰色,100%表明彻底饱和。
  • 明度 (Lightness): 明度是指颜色的亮度,取值规模为0%到100%。0%表明黑色,100%表明白色。

OpenCV 笔记(21):图画颜色空间

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

特性 HLS HSV
色相 相同 相同
饱和度 颜色与同亮度、无五颜六色(灰色)的最大差异程度 颜色纯度
亮度 感知到的明暗程度 颜色的明度
几何形状 双圆锥体和圆球体 倒圆锥体
适用规模 图形规划、用户界面 图画处理、计算机图形

OpenCV 笔记(21):图画颜色空间

2.4 YUV

YUV 颜色空间是一种运用亮度(Y)和两个色度重量(U和V)来表明颜色的颜色空间。它首要用于电视和视频领域。

YUV 颜色空间的三个重量:

  • Y:代表亮度,也便是灰度值。
  • U:代表蓝色和黄色之间的色度重量。
  • V:代表赤色和青色之间的色度重量。

OpenCV 笔记(21):图画颜色空间

由上图可知,亮度和颜色无关只是黑白灰的程度不同,因而 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油墨能够很好地吸收光线,然后发生各种各样的颜色。

OpenCV 笔记(21):图画颜色空间

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 颜色空间与设备无关,因而能够在不同的设备之间准确地转化颜色。

OpenCV 笔记(21):图画颜色空间

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;
}

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

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;
}

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

OpenCV 笔记(21):图画颜色空间

下面简单介绍一下 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. 总结

图画颜色空间在图画处理和显现中起着重要的效果。

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

图画颜色空间能够保证颜色共同性、进步图画质量、简化图画处理并促进颜色办理。随着技术的不断发展,图画颜色空间也在不断发展。