图像颜色空间
颜色模型
RGB颜色模型是最常见的颜色模型之一,常用于表示和显示图像
图像的其他模型还有YUV、HSV等,分别表示图像的亮度、色度、饱和度等
RBG颜色模型
在OpenCV中于RBG相反,第一个通道是蓝色(B),第二个通道是绿色(G),第三个通道是红色(R)
如果3种颜色分量为0,则表示为黑色,如果3种颜色分量都为最大,则表示为白色
在这个模型上增加第4个通道即为RGBA通道,第4个通道表示颜色的透明度,当没有透明度需求时RGBA模型退化为RGB模型
YUV颜色模型
这3个变量分别表示像素的亮度(Y)、红色分量于亮度的信号差值(U)、蓝色于亮度的差值(V)
这种颜色模型主要用于视频和图像的传输
HSV颜色模型
HSV是色度(Hue)、饱和度(Saturation)和亮度(Value)的简写
色度是色彩的基本属性,就是平常说的颜色
饱和度是指颜色的纯度,饱和度越高色彩越纯和艳丽,饱和度越低,色彩则逐渐地变灰和变暗,取值0~100%
亮度是颜色的明亮程度
相比于RGB模型,HSV模型更加符合人类感知颜色的方式:颜色、深浅和亮暗
Lab模型
Lab模型是一种于设备无关和基于生理特征的颜色模型
L表示亮度(Luminosity),a和b是两个颜色通道,取值是-127~128
a通道数值由小到大对应的颜色是从绿色变成红色,b通道数值由小到大对应的颜色是由蓝色变成黄色
GRAY颜色模型
GRAY模型是一个灰度图像的模型,灰度图像只有单通道,通过0~255表示
255表示白色,灰度图像具有容量小、易于采集、便于传输等优点
颜色模型转换函数cvtColor()
OpenCV提供cvtColor()函数用于实现不同颜色模型之间的相互转换
cvtColor()函数原型:
void cvtColor(InputArray src,
OutputArray dst,
int code,
int dstCn = 0
)
- src:待转换颜色模型的原始图像
- dst:转换颜色模型后的目标图像
- code:颜色空间转换的标志,如由RBG空间到HSV空间
- dstCn:目标图像中的通道数,如果参数为0,自动从src和代码中导出通道数
cvtColor()函数颜色模型转换常用标志参数
| 标志参数 | 简记 | 作用 |
|---|---|---|
| COLOR_BGR2BGRA | 0 | 对RGB图像添加alpha通道 |
| COLOR_BGR2RGB | 4 | 彩色图像通道颜色模型顺序的更改 |
| COLOR_BGR2GRAY | 10 | 彩色图像转成灰度图像 |
| COLOR_GRAY2BGR | 8 | 灰度图像转成彩色图像 |
| COLOR_BGR2YUV | 82 | RGB模型转成YUV模型 |
| COLOR_YUV2BGR | 84 | YUV模型转成RGB模型 |
| COLOR_BGR2HSV | 40 | RGB模型转成HSV模型 |
| COLOR_HSV2BGR | 54 | HSV模型转成RGB模型 |
| COLOR_BGR2Lab | 44 | RGB模型转成Lab模型 |
| COLOR_Lab1BGR | 56 | Lab模型转成RGB模型 |
示例:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("E:\\CLion\\opencv_xin\\cmake-build-debug\\lena.png");
if (img.empty())
{
cout << "Error" << endl;
return -1;
}
Mat gray,HSV,YUV,Lab,img32;
img.convertTo(img32,CV_32F,1.0/255); //将CV_8U类型转成CV_32F类型
cvtColor(img32,HSV,COLOR_BGR2HSV);
cvtColor(img32,YUV,COLOR_BGR2YUV);
cvtColor(img32,Lab,COLOR_BGR2Lab);
cvtColor(img32,gray,COLOR_BGR2GRAY);
imshow("原图",img32);
imshow("HSV",HSV);
imshow("YUV",YUV);
imshow("Lab",Lab);
imshow("gray",gray);
waitKey(0);
return 0;
}
注意:OpenCV的convertTo函数如果第三个参数使用默认的话,就会导致数值只是类型的改变
但在浮点数表示的颜色空间中,数值范围是0-1.0,基本上所有像素都转换成大于1的浮点数,截断后也就是一片白色区域
所以转换成浮点类型要写 1.0/255
数据类型转换函数convertTo()
convertTo()函数原型:
void Mat::convertTo(OutputArry m,
int rtype,
double alpha = 1,
double beta = 0
)
- m:转换类型后输出的图像
- rtype:转换图像的数据类型
- alpha:转换过程中的缩放因子
- beta:转换过程中的偏置因子
该函数用来实现将已有图像转换成指定数据类型的图像,第一个参数用于输出转换数据类型的图像
第二个参数用于声明转换后图像的数据类型,第三个参数和第四个参数用于声明两个数据类型间的转换关系
例如: m(x,y)=saturate_cast\
该转换公式可知,该转换方式就是将原有函数进行线性转换
该函数不仅可以实现不同类型之间的转换,也可以实现同一数据类型中的线性转换
注:
线性变换中最常见的一类就是所谓的矩阵变换
矩阵变换(matrix transformation)指的是这样一种把向量变成向量的对应法则:先给定一个矩阵m×n阶矩阵A,然后对于一个n维向量x,给它左边乘上A,变成Ax,根据乘法行与列的运算法则,这样得到的就是个m维向量。所以它把一个n维向量变成一个m维向量,这样的变换我们称为由矩阵A诱导出的线性变换,简称为矩阵变换。这种变换一定是线性的

矩阵变换在电脑做图中非常有用,在电脑中对一张图片进行拉伸,旋转,翻转等操作,本质就是矩阵变换。因为一张图片是由很多像素点组成的,每一个像素可以看成是一个2维向量。对图片进行操作,就相当于把每个向量都变换一下。比如我想把一张图片等比例拉伸三倍,就相当于把每一个向量都拉伸三倍,方法就是让每一个向量都乘以一个3倍单位矩阵:

于是就会产生以下的效果:

多通道分离函数split()
split()函数有两种重载类型
split()函数原型:
void split(const Mat & src,
Mat * mvbegin
)
void split(InputArry m,
OutputArrayOfArrays mv
)
- src:待转换颜色模型的原始图像
- mvbegin:分离后的单通道图像,为数组形式,数组大小需要于图像的通道数相同
- m:待分离的多通道图像
- mv:分离后的单通道图像,为向量(vector)形式
该函数主要是用于将多通道的图像分离成诺干单通道图像
前者第二个参数输出Mat类型的数组,其数组的长度需要于多通道图像的通道数相等并提前定义
后者第二个参数输出一个vector\
\
多通道合并函数merge()
merge()函数有两种重载类型
merge()函数原型:
void merge(const Mat *mv,
size_t count,
OutputArray dst
)
void merge(InputArrayOfArrays mv,
OutputArray dst
)
- mv(第一种重载类型):需要合并的图像数组,其中每个图像必须有相同的尺寸和数据类型
- count:输入的图像数组的长度,其数值必须大于0
- mv(第二种重载类型):需要合并的图像向量(vector),其中每个图像必须有相同的尺寸和数据类型
- dst:合并后输出的图像,于mv[0]具有相同的尺寸和数据类型,通道数等于所有输入图像的通道数总和
该函数主要用于将多个图像合并成一个多通道图像,该函数也具有两种不同的函数原型
与split()函数相对应,分别需要输入数组和向量的图像数据
用于合成的图像并非都是单通道的,也可以是多个不同通道数目的图像合并成一个通道更多的图像
虽然图像的通道数目可以不同,但是需要所有图像具有相同的尺寸和数据类型
示例:imshow最多显示4个通道,因此结果在Image Watch中查看
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("E:\\CLion\\opencv_xin\\cmake-build-debug\\lena.png");
if (img.empty())
{
cout << "Error" << endl;
return -1;
}
Mat HSV;
cvtColor(img,HSV,COLOR_RGB2HSV);
Mat imgs0,imgs1,imgs2; //用于存放数组类型的结果
Mat imgv0,imgv1,imgv2; //用于存放vector类型的结果
Mat result0,result1,result2; //多通道合并结果
//输入数组参数的多通道分量和合并
Mat imgs[3];
split(img,imgs);
imgs0 = imgs[0];
imgs1 = imgs[1];
imgs2 = imgs[2];
imshow("RGB-B通道",imgs0); //显示分离后B通道的像素值
imshow("RGB-G通道",imgs1); //显示分离后G通道的像素值
imshow("RGB-R通道",imgs2); //显示分离后R通道的像素值
Mat zero = Mat::zeros(img.rows,img.cols, CV_8UC1);
imgs[0] = zero;
imgs[2] = zero;
merge(imgs,3,result1); //用于还原G通道的真实情况,合并结果为绿色
imshow("reslit1",result1);
// 输入vector参数的多通道分离和合并
vector<Mat> imgv;
split(HSV,imgv);
imgv0 = imgv.at(0);
imgv1 = imgv.at(1);
imgv2 = imgv.at(2);
imshow("HSV-H通道",imgv0); //显示分离后H通道的像素值
imshow("HSV-S通道",imgv1); //显示分离后S通道的像素值
imshow("HSV-V通道",imgv2); //显示分离后V通道的像素值
merge(imgv,result2); //合并图像
imshow("result2",result2);
waitKey(0);
}
注:彩色图像一般是三通道图像(24位),一个像素需要3个值来表示分别是0-255,例如(255,178,233)。单通道(8位)只能表示一个值,范围0-255,所以都是灰度图