颜色空间:用三种或者更多特征来指定颜色的方法,被称为颜色空间或者颜色模型
颜色空间转换:OpenCV中有超过150种可用的颜色空间转换方法
最常用的是在imgproc模块中提供的void cvtColor函数
函数名 | 参数 | 解释 |
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
|
@param src input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision
floating-point.
@param dst output image of the same size and depth as src.
@param code color space conversion code (see cv::ColorConversionCodes).
@param dstCn number of channels in the destination image; if the parameter is 0, the number of the
channels is derived automatically from src and code.
|
输入图像,8或者16位无符号整形或者单精度浮点数
与src具有相同尺寸和深度的输出图像
颜色空间的转换代码
目标图像的通道数
|
颜色空间
1 RGB
一幅图像由三个独立的图像平面或者通道构成:红、蓝、绿(以及可选项:透明度alpha通道)
每个值代表每个像素的每个分量的度量值,值越高对应于更亮的像素
对应于人眼的三种光锥细胞,所以被广泛使用
2 灰度图
每个像素值只表示灰度信息这一单一信息
RGB[A]准换成灰度:Y=0.299*R+0.587*G+0.114*B
灰度转换为RGB[A]:R=Y,G=Y,B=Y,A=max(ChannelRange)
3 CLE XYZ
CLE XYZ系统采用一个亮度分量Y来描述颜色,它与人类视觉鄂亮度灵敏度和两个附加通道X,Y有关,为国际照明委员会CLE使用来自一些人观测实验的统计得到的标准
该颜色空间的主要问题是颜色以不均匀地方式被缩放
这种现象导致了CLE采用 CLE L*a*b* 和L*u*v*模型
4 YCrCb
该空间广泛用于视频和图像压缩,不能算作纯粹的色彩空间,它是RGB颜色空间的一种解码方式
Y通道表示亮度,而Cr和Cb表示红色差值(在RGB空间中R通道和Y的差值)和蓝色差值
(在RGB空间中B通道和Y的差值)各自的色度分量。
其变化计算如下:
5 HSV
HSV颜色空间输入面向色度的颜色坐标系统的一种。这种类型的颜色模型接近人类颜色感知的仿真模型。
HSV的三个通道表示色度(H给出的颜色光谱构成的一种度量),饱和度(S给出主波长中的纯光比例,这表明一种颜色距离相同亮度灰度的程度)和纯度(V给出相对于白色光照强度的亮度),对应于直觉上的色彩、明暗和色调。HSV广泛应用于色彩的比较。
TIP:OpenCV中的imshow()函数假设图像的颜色以RGB显示,因此其他显示均不正确。所以首先必须将其转换成RGB颜色空间
6 HLS
HLS属于面向色度的颜色坐标系统中的一种,和之前的HSV类似
用来指定每个通道中的一种颜色的色度值、明暗值、饱和度值
与HSV不同的是HSL定义的一种纯颜色的亮度等于一种中等灰色的亮度
而HSV定义的一种纯颜色的亮度等于白色的亮度
7 CLE L*a*b
8 CLE L*u*v
9 Bayer
Bayer像素空间组合被广泛用于只有一个图像传感器的数字相机中,每个RGB通道只有一个传感器,每个像素被一个不同颜色的滤波器覆盖掉,每个像素测量的只有一个值。使用Bayer方法时,会利用临近的像素来推断丢失的颜色信息,像素时交错分布的。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
vector<Mat > showSeparatedChannels(vector< Mat> channels );
int main()
{
//read source image
Mat src = imread("lijiang.jpg" );
imshow( "Picture", src);
//xyz
//cvtColor(src, src, COLOR_BGR2XYZ);
//vector<Mat> channels;
//split(src, channels);
//split
//vector<Mat> channels;
//cout << "-----------------1\n";
///split(src, channels);
//cout << "-----------------2\n";//不知道为啥总是出错
/*show B,G,R channels(gray)
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]);
//show B,G,R channels(colorful)
vector<Mat> separatedChannels = showSeparatedChannels(channels);
namedWindow("Blue channel", WINDOW_AUTOSIZE);
imshow("Blue channel", separatedChannels[0]);
namedWindow("Green channel", WINDOW_AUTOSIZE);
imshow("Green channel", separatedChannels[1]);
namedWindow("Red channel", WINDOW_AUTOSIZE);
imshow("Red channel", separatedChannels[2]);
Mat imageGray;
cvtColor(src, imageGray, COLOR_BGR2GRAY);
namedWindow("Gray picture", WINDOW_AUTOSIZE);
imshow("Gray picture", imageGray);
*/
/*
namedWindow("X channel(gray)", WINDOW_AUTOSIZE);
imshow("Xchannel(gray)", channels[0]);
namedWindow("Y channel(gray)", WINDOW_AUTOSIZE);
imshow("Y channel(gray)", channels[1]);
namedWindow("Z channel(gray)", WINDOW_AUTOSIZE);
imshow("Z channel(gray)", channels[2]);
vector<Mat> separatedChannels = showSeparatedChannels(channels);
for (int i = 0;i < 3;i++)
{
cvtColor(separatedChannels[i], separatedChannels[i], COLOR_XYZ2BGR);
}
namedWindow("X channel", WINDOW_AUTOSIZE);
imshow("X channel", separatedChannels[0]);
namedWindow("Y channel", WINDOW_AUTOSIZE);
imshow("Y channel", separatedChannels[1]);
namedWindow("Z channel", WINDOW_AUTOSIZE);
imshow("Z channel", separatedChannels[2]);
*/
Mat bayer = imread("lijiang.jpg" , CV_8UC3);
namedWindow( "Bayer picture", WINDOW_AUTOSIZE );
imshow( "Bayer picture", bayer);
Mat imageColor;
cvtColor(bayer, imageColor, COLOR_BayerRG2BGR);
namedWindow( "Color picture", WINDOW_AUTOSIZE );
imshow( "Color picture", imageColor);
waitKey();
return 0;
}
vector<Mat > showSeparatedChannels(vector< Mat> channels )
{
vector<Mat > separatedChannels;
for (int i = 0; i < 3; i++)
{
Mat zer = 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(zer);
}
}
Mat chann;
merge(aux, chann);
separatedChannels.push_back(chann);
}
return separatedChannels;
}
基于颜色空间的分割
When the lower and/or upper boundary parameters are scalars, the indexes
(I) at lowerb and upperb in the above formulas should be omitted.
@param src first input array.
@param lowerb inclusive lower boundary array or a scalar.
@param upperb inclusive upper boundary array or a scalar.
@param dst output array of the same size as src and CV_8U type.
*/
CV_EXPORTS_W
void
inRange(InputArray src, InputArray lowerb,
InputArray upperb, OutputArray dst);
利用HSV空间
利用YCrCb空间
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
//read source image
Mat src = imread("hand.png" );
imshow( "Picture", src);
//Mat hsv;
//cvtColor(src, hsv, COLOR_BGR2HSV);
//Mat bw;
//inRange(hsv, Scalar(0, 10, 60), Scalar(20, 150, 255), bw);
Mat ycrcb;
Mat bw;
cvtColor(src, ycrcb, COLOR_BGR2YCrCb);
inRange(ycrcb, Scalar(0, 133, 77), Scalar (255, 173, 177), bw);
namedWindow( "Selected pixels", WINDOW_AUTOSIZE );
imshow( "Selected pixels", bw);
waitKey();
return 0;
}