颜色空间
要用三种或更多的特征来指定一种颜色,有许多的方法被称为颜色空间或者颜色模型。
如何选取其中一种方法来表示一副图像要依赖于执行的运算。
不同的颜色空间的转换,Opencv提供方法
void cvtColor(InputArray src, Output dst, int code, int dstCn=0)
code : 这是颜色空间的转换代码。例如COLOR_BGR2GRAY
dstCn:这是目标图形的通道数,如果为0或省略,则通道数有src和code自动产生。
常用的颜色空间:
RGB颜色空间
在RGB中,一幅图像有三个独立的图像平面或通道组成:红,绿,蓝(以及第四个通道透明度)。
如下代码展示了,加载RGB图像,并在灰度空间和颜色空间中拆分并显示每个特定的通道。
void split(InputArray m, OutputArrayOfArrays mv)
1. 将图像的每个通道保存在mv中
2. mv声明为vector mv
void merge(InputArrayOfArrays mv, OutputArray dst)
1. 将mv和并称一个图像dst
#include "opencv2/opencv.hpp"
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<iostream>
using namespace cv;
using namespace std;
vector<Mat> showSeqratedChannels(vector<Mat> channels);
int main() {
Mat image = imread("test.jpg");
vector<Mat> channels;
split(image, channels); //分割图像
//用灰度级显示通道
namedWindow("Origin", WINDOW_NORMAL);
imshow("Origin", image);
namedWindow("Blue channel",WINDOW_NORMAL);
imshow("Blue channel", channels[0]);
namedWindow("Green channel", WINDOW_NORMAL);
imshow("Green channel", channels[1]);
namedWindow("Red channel", WINDOW_NORMAL);
imshow("Red channel", channels[2]);
cout << channels.size() << endl;
//显示BGR中的通道
vector<Mat> separated = showSeqratedChannels(channels);
namedWindow("Blue channel", WINDOW_AUTOSIZE);
imshow("Blue channel", separated[0]);
namedWindow("Green channel", WINDOW_AUTOSIZE);
imshow("Green channel", separated[1]);
namedWindow("Red channel", WINDOW_AUTOSIZE);
imshow("Red channel", separated[2]);
cout << separated[0].size() << endl;
cout << separated[0].rows << endl;
cout << separated[0].cols << endl;
waitKey();
}
//这个函数,将channels中的每个波段分别加上两个波段,形参三个RGB通道
//其余两个通道介入的都是0像素。
vector<Mat> showSeqratedChannels(vector<Mat> channels) {
vector<Mat> seqaratedChannels;
for (int i = 0; i < 3; i++) {
Mat zero = Mat::zeros(channels[0].rows, channels[0].cols, channels[0].type());
vector<Mat>aux;
for (int j = 0; j < 3; j++) {
if (j == i) aux.push_back(channels[i]);
else
aux.push_back(zero);
}
Mat chann;
merge(aux, chann); //chann为输出的容器
seqaratedChannels.push_back(chann);
}
return seqaratedChannels;
}
原始的图像如下所示:
用灰度级显示通道:
显示BGR中的通道:
灰度图像与RGB图像的转变。
RGB[A]转换为灰度:Y=0.299*R+0.587*G+0.114*B;
用cvtColor
方法的缺陷就是是的原始图像的对比度丢失,从上面的式子中可以看到。
//利用opencv函数将彩色变为灰度图像
cvtColor(image,imageGray,COLOR_BGR2GRAY);
CIE XYZ颜色空间
CIE XYZ系统用一个亮度分类Y来描述颜色,他与人类视觉的亮度灵敏度和两个附加通道X,Z相关。
RGB和CIE XYZ之间的转换颜色空间代码是:
COLOR_BGR2XYZ
COLOR_RGB2XYZ
COLOR_XYZ2BGR
COLOR_XYZ2RGB
它与RGB的转换公式如下图所示:
下面代码是将RGB图像转换成XYZ空间,以及在灰度空间和颜色空间中拆分并显示特定通道。
#include "opencv2/opencv.hpp"
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<iostream>
using namespace cv;
using namespace std;
vector<Mat> showSeqratedChannels(vector<Mat> channels);
int main() {
Mat image = imread("cute.jpg");
namedWindow("Origin", WINDOW_AUTOSIZE);
imshow("Origin", image);
cvtColor(image, image, CV_BGR2XYZ);
namedWindow("Origin_XYZ", WINDOW_AUTOSIZE);
imshow("Origin_XYZ", image);
vector<Mat> channels;
split(image, channels); //分割图像
//用灰度级显示通道
namedWindow("Blue channel_GRAY",WINDOW_AUTOSIZE);
imshow("Blue channel_GRAY", channels[0]);
namedWindow("Green channel_GRAY", WINDOW_AUTOSIZE);
imshow("Green channel_GRAY", channels[1]);
namedWindow("Red channel_GRAY", WINDOW_AUTOSIZE);
imshow("Red channel_GRAY", channels[2]);
cout << channels.size() << endl;
显示BGR中的通道
vector<Mat> separated = showSeqratedChannels(channels);
for (int i = 0; i < 3; i++) {
cvtColor(separated[i], separated[i], COLOR_XYZ2BGR); //在将其转成BGR中显示通道
}
namedWindow("Blue channel", WINDOW_AUTOSIZE);
imshow("Blue channel", separated[0]);
namedWindow("Green channel", WINDOW_AUTOSIZE);
imshow("Green channel", separated[1]);
namedWindow("Red channel", WINDOW_AUTOSIZE);
imshow("Red channel", separated[2]);
cout << separated[0].size() << endl;
cout << separated[0].rows << endl;
cout << separated[0].cols << endl;
waitKey();
}
vector<Mat> showSeqratedChannels(vector<Mat> channels) {
vector<Mat> seqaratedChannels;
for (int i = 0; i < 3; i++) {
Mat zero = Mat::zeros(channels[0].rows, channels[0].cols, channels[0].type());
vector<Mat>aux;
for (int j = 0; j < 3; j++) {
if (j == i) aux.push_back(channels[i]);
else
aux.push_back(zero);
}
Mat chann;
merge(aux, chann); //chann为输出的容器
seqaratedChannels.push_back(chann);
}
return seqaratedChannels;
}
YCrCb颜色空间
该颜色空间广泛的用于视频压缩和图像压缩方案,不能算是纯粹的颜色空间,因为它是RGB颜色空间的一种解码方式。
该颜色空间广泛的应用于MPEG和JPEG等视频和图像压缩方案。
Y表示亮度
Cr : RGB空间R通道和Y差值
Cb: RGB空间B通道和Y差值
RGB和YCrCb之间的转换颜色空间代码是:
COLOR_BGR2YCrCb
COLOR_RGB2YCrCb
COLOR_YCrCb2BGR
COLOR_YCrCb2RGB
计算的过程如下图所示:
同理,将一副RGB图像转换成YCrCb空间,以及在灰度空间和颜色空间中拆分并显示特定通道代码同上述非常类似,因此不再重复。
效果如下图所示:
HSV颜色空间
HSV颜色空间属于面向色度的颜色坐标系的一种,这种颜色模型接近于人类颜色感知的仿真模型,而在其他颜色模型中,例如RGB,一副图像被视为3中基色的叠加。
H(hue): 色调,取值[0,1],对应颜色的种类,颜色从红,通过黄,绿,蓝,紫和黑到红。
S(saturation):饱和度,取值[0,1],对应预色调种类从不饱和(灰度梯度)到完全饱和(无白色)。
V(value):取值[0,1],对应色彩有暗变亮。
OpenCV中使用在RGB,HSV之间变换的颜色空间转换代码:
COLOR_BGR2HSV
COLOR_RGB2HSV
COLOR_HSV2BGR
COLOR_HSV2RGB
如果src图像格式是8位或16位,则首先转成一个浮点格式,将其值变化成0到1之间,在计算: