- 1
-
颜色 的 三 要素 : 色调 , 饱和度 , 和 亮度 。
-
将图像的RGB值转换成色调、饱和度和亮度值,并将色调和饱和度结合产生融合图像,以消除地表、天空等背景的影响。
The color image was translated from RGB system to HSI system, and the hue, lightness and saturation images were acquired. In order to eliminate the influence of background of soil and sky, the hue and saturation data was combined and produced fusion image.
-
由于RGB空间仅利用亮度信息而较少利用颜色信息,并且该空间三分量高度相关,与人类视觉倾向于用色调、饱和度和亮度共同描述彩色物体不一致,不适合于边缘检测任务。
RGB color space using only the brightness information and less use of color information, and the space three components are highly correlated, human vision prefers to use hue, saturation and brightness to describe the color object is inconsistent, not suitable for edge detection task.
openCv RGB到HSV空间的学习
版权声明:本文为博主原创文章,未经博主允许不得转载。
这次我主要说说颜色空间,包括三个方面:RGB颜色空间,HSV颜色空间以及颜色空间的转换
RGB颜色空间介绍:
1: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:单通道图像亮度显示也是通过下图来显示的
得到上图的代码为:
- #include <iostream>
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- using namespace std;
- int main()
- {
- IplImage *dst = cvCreateImage(cvSize(255, 255), 8, 3);
- for(int y = dst->height - 1; y >= 0; y--)
- {
- cvSet2D(dst, y, dst->height - y - 1, cvScalar(255-y, 255-y, 255-y));
- }
- cvNamedWindow("show");
- cvShowImage("show", dst);
- cvWaitKey(0);
- cvReleaseImage(&dst);
- cvDestroyWindow("show");
- return 0;
- }
#include <iostream>
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
using namespace std;
int main()
{
IplImage *dst = cvCreateImage(cvSize(255, 255), 8, 3);
for(int y = dst->height - 1; y >= 0; y--)
{
cvSet2D(dst, y, dst->height - y - 1, cvScalar(255-y, 255-y, 255-y));
}
cvNamedWindow("show");
cvShowImage("show", dst);
cvWaitKey(0);
cvReleaseImage(&dst);
cvDestroyWindow("show");
return 0;
}
HSV颜色空间
H:色调 0°对应红色, 120°对应绿色, 240°对应蓝色---对应不同的颜色 取值范围0~360度
S:饱和度 比若说:红色的纯度,越白纯度越低,取值范围0~1
V:亮度 比如你穿了一件红色衣服 在白天亮度较高(0~255之间)傍晚或者黄昏就比较低(0~255之间),即多少的光照上去反射出来被看见,取值范围0~255
如图:
颜色空间的转换
用到的核心函数有: 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之间。
代码:
- #include <iostream>
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- using namespace std;
- int main()
- {
- IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);
- IplImage *hsv_img = cvCreateImage(cvGetSize(src), 8 , 3);
- IplImage *h_img = cvCreateImage(cvGetSize(src), 8, 1);
- IplImage *s_img = cvCreateImage(cvGetSize(src), 8, 1);
- IplImage *v_img = cvCreateImage(cvGetSize(src), 8, 1);
- cvCvtColor(src, hsv_img, CV_BGR2HSV);
- cvSplit(hsv_img, h_img, s_img, v_img, NULL);
- for(int y = 0; y < hsv_img->height; y++){
- for(int x = 0; x < hsv_img->width; x++)
- {
- cout << cvGetReal2D(h_img, y, x) << " ";
- }
- cout << endl;
- }
- cvNamedWindow("src", 0);
- cvShowImage("src", hsv_img);
- cvWaitKey(0);
- cvReleaseImage(&src);
- cvDestroyWindow("src");
- return 0;
- }
#include <iostream>
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
using namespace std;
int main()
{
IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);
IplImage *hsv_img = cvCreateImage(cvGetSize(src), 8 , 3);
IplImage *h_img = cvCreateImage(cvGetSize(src), 8, 1);
IplImage *s_img = cvCreateImage(cvGetSize(src), 8, 1);
IplImage *v_img = cvCreateImage(cvGetSize(src), 8, 1);
cvCvtColor(src, hsv_img, CV_BGR2HSV);
cvSplit(hsv_img, h_img, s_img, v_img, NULL);
for(int y = 0; y < hsv_img->height; y++){
for(int x = 0; x < hsv_img->width; x++)
{
cout << cvGetReal2D(h_img, y, x) << " ";
}
cout << endl;
}
cvNamedWindow("src", 0);
cvShowImage("src", hsv_img);
cvWaitKey(0);
cvReleaseImage(&src);
cvDestroyWindow("src");
return 0;
}
2:将色调H的取值范围转换到0~360之间
- #include <iostream>
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- using namespace std;
- int main()
- {
- IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);
- IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);
- <span style="color: rgb(255, 0, 0);">cvConvertScale(src, src_float, 1.0, 0.0);
- IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);
- IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- </span>
- cvCvtColor(src_float, hsv_img, CV_BGR2HSV);
- cvSplit(hsv_img, h_img, s_img, v_img, NULL);
- for(int y = 0; y < hsv_img->height; y++){
- for(int x = 0; x < hsv_img->width; x++)
- {
- cout << cvGetReal2D(h_img, y, x) << " ";
- }
- cout << endl;
- }
- cvNamedWindow("src", 0);
- cvShowImage("src", hsv_img);
- cvWaitKey(0);
- cvReleaseImage(&src);
- cvDestroyWindow("src");
- return 0;
- }
#include <iostream>
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
using namespace std;
int main()
{
IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);
IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);
<span style="color: rgb(255, 0, 0);">cvConvertScale(src, src_float, 1.0, 0.0);
IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);
IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
</span>
cvCvtColor(src_float, hsv_img, CV_BGR2HSV);
cvSplit(hsv_img, h_img, s_img, v_img, NULL);
for(int y = 0; y < hsv_img->height; y++){
for(int x = 0; x < hsv_img->width; x++)
{
cout << cvGetReal2D(h_img, y, x) << " ";
}
cout << endl;
}
cvNamedWindow("src", 0);
cvShowImage("src", hsv_img);
cvWaitKey(0);
cvReleaseImage(&src);
cvDestroyWindow("src");
return 0;
}
3:将H,S,V的范围转化到0~255之间
- #include <iostream>
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- using namespace std;
- int main()
- {
- IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);
- IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);
- cvConvertScale(src, src_float, 1.0, 0.0);
- IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);
- IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
- <span style="color: rgb(255, 0, 0);">
- IplImage *h = cvCreateImage(cvGetSize(src), 8, 1);
- IplImage *s = cvCreateImage(cvGetSize(src), 8, 1);
- IplImage *v = cvCreateImage(cvGetSize(src), 8, 1);
- cvCvtColor(src_float, hsv_img, CV_BGR2HSV);
- cvSplit(hsv_img, h_img, s_img, v_img, NULL);
- cvConvertScale(h_img, h, (1.0/360)*255, 0.0);
- cvConvertScale(s_img, s, 255.0, 0.0); // 因为S的取值范围为0~1
- cvConvertScale(v_img, v, 1.0, 0.0);</span>
- for(int y = 0; y < hsv_img->height; y++){
- for(int x = 0; x < hsv_img->width; x++)
- {
- if(cvGetReal2D(h, y, x) > 200)cout << cvGetReal2D(h, y, x) << " ";
- }
- cout << endl;
- }
- cvNamedWindow("src", 0);
- cvShowImage("src", hsv_img);
- cvWaitKey(0);
- cvReleaseImage(&src);
- cvDestroyWindow("src");
- return 0;
- }