【RGB颜色空间】
1、三基色模式:
RGB颜色空间以R(Red:红)、G(Green:绿)、B(Blue:蓝)三种基本色为基础,进行不同程度的叠加,产生丰富而广泛的颜色,所以俗称三基色模式。
2、空间模型
RGB颜色空间是用一个单位长度的立方体来表示颜色的,黑蓝绿青红紫黄白8种常见颜色分别位居立方体的8个顶点,通常将黑色置于三维直角坐标系的原点,红绿蓝分别置于3根坐标轴土,整个立方体放在第1卦限内。
3、各参数的取值范围是:
R:0-255
G:0-255
B:0-255
参数值也称为三色系数或基色系数或颜色值,除以255后归一到0-1之间,但不是无穷多个而是有限多个值。
4、互补色
其中的青色与红色、紫色(或称品红色)与绿色、黄色与蓝色是互补色。
5、相加混色法
红色+绿色 = 黄色
绿色+蓝色 = 青色
红色+蓝色 = 品红(紫色)
红色+绿色+蓝色 = 白色
红色+青色 = 白色
绿色+品红 = 白色
蓝色+黄色 = 白色
6、亮度的定义:
单色光的亮度强度各不相同,根据人的感受是:绿光最高,红光次之,蓝光最弱,假设得到的白光的强度为100%。如果用Y表示景物的亮度,则通常有:
Y= 0.299R + 0.587G + 0.114B
【HSV颜色空间】
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
HSV(Hue Saturation Value)颜色模型是面向用户的。
1、颜色的参数
色调(H),饱和度(S),明度(V)
色调(H))
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°
饱和度(S)
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和
明度(V)
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)
2、六角锥体模型(Hexcone Model)
H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一
角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。
纯度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。
V表示色彩的明亮程度,范围从0到1。有一点要注意:它和光强度之间并没有直接的联系。
3、RGB和HSV之间的转换
(1)从RGB到HSV
设max等于r、g和b中的最大者,min为最小者。对应的HSV空间中的(h,s,v)值为:
h在0到360°之间,s在0到100%之间,v在0到max之间。
(2)从HSV到RGB
【YUV颜色空间】
1、YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法。在现代彩色电视系统中,通常采用三管彩色摄像机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y(即U)、B-Y(即V),最后发送端将亮度和两个色差总共三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V信号分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
2、YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。
3、YUV和RGB互相转换的公式如下(RGB取值范围均为0-255)︰
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
【灰度图】
在计算机领域中,这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;灰度图像在黑色与白色之间还有许多级的颜色深度。
我们可以通过下面几种方法,将其转换为灰度:
1.浮点算法:Gray=R*0.3+G*0.59+B*0.11
2.整数方法:Gray=(R*30+G*59+B*11)/100
3.移位方法:Gray =(R*76+G*151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。
【HSV检测特定颜色】
1、实现流程
2、源代码
/************************************************************************
* @ Creator:OYXL
* @ Project Creation time:2018/5/22
* @ Function:HSV color space conversion detects a specific color, where the detection color is yellow.
* @ Attention:May detect a variety of colors.
************************************************************************/
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace cv;
using namespace std;
/************************************************************************
*< @ 函数:line()
*< @ img: 要绘制线段的图像。
*< @ pt1: 线段的起点。
*< @ pt2: 线段的终点。
*< @ color: 线段的颜色,通过一个Scalar对象定义。
*< @ thickness: 线条的宽度。
*< @ lineType: 线段的类型,可以取值8,4,和CV_AA,分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
*< @ shift: 坐标点小数点位数。
/************************************************************************/
int main()
{
VideoCapture cap(0); //capture the video from web cam
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
namedWindow("Control", CV_WINDOW_NORMAL); //create a window called "Control"
int iLowH =19;
int iHighH =180;
int iLowS = 43;
int iHighS = 255;
int iLowV = 46;
int iHighV = 255;
Mat imgOriginal;
vector<vector<Point>> contours;
vector<Vec4i> Hierarchy;
Mat imgHSV;
vector<Mat> hsvSplit;
//Create trackbars in "Control" window
cvCreateTrackbar("LowH", "Control", &iLowH, 180); //Hue (0 - 180)
cvCreateTrackbar("HighH", "Control", &iHighH, 180);
cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("HighS", "Control", &iHighS, 255);
cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
cvCreateTrackbar("HighV", "Control", &iHighV, 255);
while (true)
{
cap>>imgOriginal;
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
//<hsv[2] 是v通道 做亮度均衡
//GaussianBlur();
split(imgHSV, hsvSplit);
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, imgHSV);
Mat imgThresholded;
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image
//open (remove noise)
Mat element1 = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element1);
//close (connect connected-component)
Mat element2= getStructuringElement(MORPH_RECT, Size(10,10));
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element2);
Canny(imgThresholded,imgThresholded,3,9,3);
findContours(imgThresholded,contours,Hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
vector<Moments> Mu(contours.size());
vector<Point> Mc(contours.size());
vector<RotatedRect> box(contours.size());
Point2f vertex[4];
if(contours.size()>0)
{
for (int i=0;i<contours.size();i++)
{
box[i]=minAreaRect(Mat(contours[i]));
box[i].points(vertex);
Mu[i] = moments(contours[i],false);//<容器下标越界
Mc[i] = Point(static_cast<int>(Mu[i].m10 / Mu[i].m00), static_cast<int>(Mu[i].m01 / Mu[i].m00));//center.x = (int)(m10 / m00);center.y = (int)(m01 / m00);
circle(imgOriginal,Mc[i],5,Scalar(0,255,0),1,CV_AA);
drawContours(imgOriginal,contours,i,Scalar(0,255,0),1,8,Hierarchy,0,Point(0,0));
for (int j=0;j<4;j++)
{
line(imgOriginal,vertex[j],vertex[(j+1)%4],Scalar(0,255,0),2,CV_AA);
}
}
}
imshow("Thresholded Image", imgThresholded); //show the thresholded image
imshow("Original", imgOriginal); //show the original image
Mu.clear();
Mc.clear();
box.clear();
char key = (char)waitKey(25);
if (key == 27)
break;
}
return 0;
}
3、效果图