《OpenCV颜色空间及颜色空间相互转化》

【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参数表示色彩信息,即所处的光谱颜色的位置。该参数用一
HSV颜色空间模型 HSV颜色空间模型
角度量来表示,红、绿、蓝分别相隔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、效果图



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值