为了识别图像中的特定颜色(红绿黄等),常常将彩色图片转换为HSV图片,限定HSV取值范围既可以获取需要的颜色。
1.HSV模型
倒圆锥模型,HSV就是按照色彩、深浅、明亮来描述的。
H表示色彩,亦色调
S表示深浅,S=0时,只有灰度,亦饱和度
V表示明亮,色彩的明亮程度,亦亮度,该值与光强没有直接联系。
代码实现的角度可以用下面的方式(作用和上面的公式一样):
RGB转换为HSV公式:
在不同的软件编程下,H值的求取细节会有少许不同。
1.1Matlab中rgb转Hsv
**hv0 = rgb2hsv(I0)**;
figure;imshow(I0);title('彩色原图');
%可以通过下面的程序看一幅图的HSV三个通道
H0=hv0(:,:,1)* 255;
S0=hv0(:,:,2)* 255;
V0=hv0(:,:,3)* 255;
由于运用rgb2hsv转换后的hv0是浮点数,为了后续通道处理与显示,对每个通道*255.
彩色图像I0(:,:,1) -> R I0(:,:,2) -> G I0(:,:,3) -> B
1.2 opencv(3.0) rgb转换为hsv
Mat bgrimage = imread("C:\\1.bmp");
Mat hsvimage;
**cvtColor(bgrimage, hsvimage, CV_BGR2HSV)**;
opencv
bgrimage.at(i, j).val[0] -> B
bgrimage.at(i, j).val[1] -> G
bgrimage.at(i, j).val[2] -> R
hsvimage.at(i, j).val[0] -> H
hsvimage.at(i, j).val[1] -> S
hsvimage.at(i, j).val[2] -> V
此处无需在进行转换,可以直接显示Mat 型HSV图
1.3 Emgucv 转换
private Image<Bgr, byte> bgrImg;//原彩色图像
private Image<Hsv, byte> hsvImg;//转换为Hsv图像
hsvImg = new Image<Hsv, byte>(bgrImg.Width, bgrImg.Height);
hsvImg = **bgrImg.Convert<Hsv, byte>()**;
或者
hsvImg = new Image<Hsv, byte>(bgrImg.Width, bgrImg.Height);
CvInvoke.CvtColor(bgrImg, hsvImg, Emgu.CV.CvEnum.ColorConversion.Bgr2Hsv);
pictureBox1.Image = hsvImg.Bitmap;
错误格式:
Image<Bgr, float> bgrFImg = new Image<Bgr, float>(bgrImg.Width, bgrImg.Height);
Image<Hsv, float> hsvFImg = new Image<Hsv, float>(bgrImg.Width, bgrImg.Height);
hsvImg = new Image<Hsv, byte>(bgrImg.Width, bgrImg.Height);
CvInvoke.cvConvertScale(bgrImg, bgrFImg, 1.0, 0);//将原图转换为float型
CvInvoke.CvtColor(bgrFImg, hsvFImg, Emgu.CV.CvEnum.ColorConversion.Bgr2HsvFull);
CvInvoke.cvConvertScale(hsvFImg, hsvImg, 1.0, 0);
这种方法求出的S恒等于0
1.4自己实现代码
float retmax(float a,float b,float c)//求最大值
{
float max = 0;
max = a;
if(max<b)
max = b;
if(max<c)
max = c;
return max;
}
float retmin(float a,float b,float c)//求最小值
{
float min = 0;
min = a;
if(min>b)
min = b;
if(min>c)
min = c;
return min;
}
//R,G,B参数传入范围(0~100)
//转换结果h(0~360),s(0~100),v(0~100)
void rgb_to_hsv(float *h,float *s,float *v,float R,float G,float B)
{
float max = 0,min = 0;
R = R/100;
G = G/100;
B = B/100;
max = retmax(R,G,B);
min = retmin(R,G,B);
*v = max;
if(max == 0)
*s = 0;
else
*s = 1 - (min/max);
if(max == min)
*h = 0;
else if(max == R && G>=B)
*h = 60*((G-B)/(max-min));
else if(max == R && G<B)
*h = 60*((G-B)/(max-min)) + 360;
else if(max == G)
*h = 60*((B-R)/(max-min)) + 120;
else if(max == B)
*h = 60*((R-G)/(max-min)) + 240;
*v = *v * 100;
*s = *s * 100;
}
2.从HSV转换到RGB
转换公式:
其中floor表示向下取整
自己实现代码
//参数入参范围h(0~360),s(0~100),v(0~100),这里要注意,要把s,v缩放到0~1之间
//转换结果R(0~100),G(0~100),B(0~100),如需转换到0~255,只需把后面的乘100改成乘255
void hsv_to_rgb(int h,int s,int v,float *R,float *G,float *B)
{
float C = 0,X = 0,Y = 0,Z = 0;
int i=0;
float H=(float)(h);
float S=(float)(s)/100.0;
float V=(float)(v)/100.0;
if(S == 0)
*R = *G = *B = V;
else
{
H = H/60;
i = (int)H;
C = H - i;
X = V * (1 - S);
Y = V * (1 - S*C);
Z = V * (1 - S*(1-C));
switch(i){
case 0 : *R = V; *G = Z; *B = X; break;
case 1 : *R = Y; *G = V; *B = X; break;
case 2 : *R = X; *G = V; *B = Z; break;
case 3 : *R = X; *G = Y; *B = V; break;
case 4 : *R = Z; *G = X; *B = V; break;
case 5 : *R = V; *G = X; *B = Y; break;
}
}
*R = *R *100;
*G = *G *100;
*B = *B *100;
}
参考
(318条消息) RGB 和 HSV 互相转换算法_rgb转hsv公式_lly_3485390095的博客-CSDN博客
bgr转换为Hsv(Matlab、OpenCV、Emgucv)_matlab bgr转hsv公式_黑框追光者的博客-CSDN博客