HSV取值范围

来源:互联网 发布:淘宝代理e商网靠谱吗 编辑:程序博客网 时间:2024/04/28 03:38

这次我主要说说颜色空间,包括三个方面:RGB颜色空间,HSV颜色空间以及颜色空间的转换

RGB颜色空间介绍:

1:RGB颜色空间简介

         三基色原理:大多数的颜色可以通过红、绿、蓝<数学中基的概念>三色按照不同的比例合成产生,同样绝大多数单色光也可以分解成红绿蓝三种色光

         红绿蓝三基色按照不同的比例相加合成混色称为相加混色。其中一些混色的规律有:

                   红色+绿色 = 黄色

                   绿色+蓝色 = 青色

                   红色+蓝色 = 品红

                   红色+绿色+蓝色 = 白色

                   红色+青色 = 白色

                   绿色+品红 = 白色

                   蓝色+黄色 = 白色

下图为RGB空间:

2:互补光的定义:

         当两种光按照适当比例混合得到白光时,称这两种光为互补光。所以上述的混色规律我们可以得到青色、黄色、品红分别是红色、蓝色、绿色的补色。

 

3:亮度的定义:

         单色光的亮度强度各不相同,根据人的感受是:绿光最高,红光次之,蓝光最弱,假设得到的白光的强度为100%。如果用Y表示景物的亮度,则通常有:

                   Y= 0.299R + 0.587G + 0.114B

因为红﹑绿﹑蓝三基色能够合成自然界所有的色彩,因此在电子设备和软件中,经常使用红绿蓝三基色合成五颜六色的图像。用以上的相加混色所表示的颜色模式成为RGB模式

注意:

1:CvLoadImage(“”,0)所得到的图像即为灰度单通道图像,所对应的像素即为Y;而与split函数得到的单通道图像R,G,B不一样,但其亮度显示也是按照下图的直线来显示的<即为RGB空间的直线>

2:三通道图像也可能是灰度图像,当三通道值相等时,所对应的三通道图像就是灰度图像<可以通过以下程序画出来>。即RGB space空间中(0,0,0)和(1,1,1)两线上所有点就是灰度图像—>三通道图不一定是彩色的,彩色图一定是三通道的

3:cvCvtColor(src,dst,CV_GRAY2BGR);  //此时dst三通道的值都相等,都等于src单通道的值,因此结果仍然是灰度图像,这个函数实质不起任何作用。。

4:单通道图像亮度显示也是通过下图来显示的

得到上图的代码为:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5. using namespace std;  
  6. int main()  
  7. {  
  8.     IplImage *dst = cvCreateImage(cvSize(255, 255), 8, 3);  
  9.     for(int y = dst->height - 1; y >= 0; y--)  
  10.     {  
  11.         cvSet2D(dst, y,  dst->height - y - 1, cvScalar(255-y, 255-y, 255-y));  
  12.     }  
  13.     cvNamedWindow("show");  
  14.     cvShowImage("show", dst);  
  15.     cvWaitKey(0);  
  16.     cvReleaseImage(&dst);  
  17.     cvDestroyWindow("show");  
  18.     return 0;  
  19. }  

HSV颜色空间

H:色调 0°对应红色, 120°对应绿色, 240°对应蓝色---对应不同的颜色 取值范围0~360

S:饱和度  比若说:红色的纯度,越白纯度越低,取值范围0~1

V:亮度  比如你穿了一件红色衣服 在白天亮度较高(0~255之间)傍晚或者黄昏就比较低(0~255之间)即多少的光照上去反射出来被看见,取值范围0~255,因为其转换公式是统一的,如下:


   注意:其实不同的软件进行量化的取值范围是不同的,例如PS软件里的h取值为0-360、s取值为0-1、v取值为0-1.

而opencv里cvSplit使用的图像是32F则其取值是h为0-360、s取值为0-1、v取值为0-255。如果是8UC则取值范围是h为0-180、s取值为0-255、v取值是0-255.  其中h色调对图像的分辨是很准的。

如图:


注意: 如果一个颜色的饱和度偏低,会导致色调信息变得不稳定以及不可靠。这是因为低饱和度的颜色中,红绿蓝三个分量几乎是相等的。这使得难以确定精确的颜色。


颜色空间的转换

用到的核心函数有: cvConvertScale, cvSplit, cvMerge, cvCvtColor

需要注意的是:由于加载进来图像是uchar,最多只能是255,而OpenCV正常程序的结构显示H色调都会小于等于180<因为程序知道表示不了360,直接全部缩小到180>,而H色调的取值范围0~360,因此我们需要将图像转换成float类型,而cvConvertScale 可以实现放大缩小偏移同时可以做类型转换;之后我们可以将hsv各通道转换到0~255之间,使用到的函数仍然是cvConvertScale 。最后需要注意的一点是:CvShowImage显示的图像都会被当做RGB颜色空间的图像来处理.

下面给出这之间范围变化的代码:

1:没有考虑H(色调)范围的代码,此时H的范围只能在0~180之间。

代码:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5.   
  6. using namespace std;  
  7.   
  8. int main()  
  9. {  
  10.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  11.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), 8 , 3);  
  12.     IplImage *h_img = cvCreateImage(cvGetSize(src), 8, 1);  
  13.     IplImage *s_img = cvCreateImage(cvGetSize(src), 8, 1);  
  14.     IplImage *v_img = cvCreateImage(cvGetSize(src), 8, 1);  
  15.   
  16.     cvCvtColor(src, hsv_img, CV_BGR2HSV);  
  17.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  18.     for(int y = 0; y < hsv_img->height; y++){  
  19.         for(int x = 0; x < hsv_img->width; x++)  
  20.         {  
  21.             cout << cvGetReal2D(h_img, y, x) << " ";  
  22.         }  
  23.         cout << endl;  
  24.     }  
  25.     cvNamedWindow("src", 0);  
  26.     cvShowImage("src", hsv_img);  
  27.     cvWaitKey(0);  
  28.     cvReleaseImage(&src);  
  29.     cvDestroyWindow("src");  
  30.     return 0;  
  31. }  

2:将色调H的取值范围转换到0~360之间

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5.   
  6. using namespace std;  
  7.   
  8. int main()  
  9. {  
  10.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  11.     IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);  
  12.     cvConvertScale(src, src_float, 1.0, 0.0);  
  13.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  
  14.     IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  15.     IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  16.     IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  17. </span>  
  18.     cvCvtColor(src_float, hsv_img, CV_BGR2HSV);  
  19.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  20.     for(int y = 0; y < hsv_img->height; y++){  
  21.         for(int x = 0; x < hsv_img->width; x++)  
  22.         {  
  23.             cout << cvGetReal2D(h_img, y, x) << " ";  
  24.         }  
  25.         cout << endl;  
  26.     }  
  27.     cvNamedWindow("src", 0);  
  28.     cvShowImage("src", hsv_img);  
  29.     cvWaitKey(0);  
  30.     cvReleaseImage(&src);  
  31.     cvDestroyWindow("src");  
  32.     return 0;  
  33. }  

3:将H,S,V的范围转化到0~255之间

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4. #include "cxcore.h"  
  5.   
  6. using namespace std;  
  7.   
  8. int main()  
  9. {  
  10.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  11.     IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);  
  12.     cvConvertScale(src, src_float, 1.0, 0.0);  
  13.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  
  14.     IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  15.     IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  16.     IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  17.     IplImage *h = cvCreateImage(cvGetSize(src), 8, 1);  
  18.     IplImage *s = cvCreateImage(cvGetSize(src), 8, 1);  
  19.     IplImage *v = cvCreateImage(cvGetSize(src), 8, 1);  
  20.   
  21.     cvCvtColor(src_float, hsv_img, CV_BGR2HSV);  
  22.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  23.     cvConvertScale(h_img, h, (1.0/360)*255, 0.0);  
  24.     cvConvertScale(s_img, s, 255.0, 0.0);  // 因为S的取值范围为0~1,因为其是32F,如果是8uc则是0-255 
  25.     cvConvertScale(v_img, v, 1.0, 0.0); 
  26.     for(int y = 0; y < hsv_img->height; y++){  
  27.         for(int x = 0; x < hsv_img->width; x++)  
  28.         {  
  29.             if(cvGetReal2D(h, y, x) > 200)cout << cvGetReal2D(h, y, x) << " ";  
  30.         }  
  31.         cout << endl;  
  32.     }  
  33.     cvNamedWindow("src", 0);  
  34.     cvShowImage("src", hsv_img);  
  35.     cvWaitKey(0);  
  36.     cvReleaseImage(&src);  
  37.     cvDestroyWindow("src");  
  38.     return 0;  
  39.   
  40. }  







0 0