基于RGB与HSI颜色模型的图像提取法
现实中我们要处理的往往是RGB彩色图像。对其主要通过HSI转换、分量色差等技术来提出目标。
RGB分量灰度化:
RGB可以分为R、G、B三分量。当R=G=B即为灰度图像,很多时候为了方便,会直接利用某个分量来进行灰度化,如下图所示:
上图中R分量下红色部分明显比其他两幅更偏白;同样地G分量草地较淡,B分量天空较淡。其他部分如灰黑色马路则相差不多。实际中,我们可以根据
需求有选择地选择分量。
RGB分量差灰度化:
有时候我们的要求是从图像中提取某种颜色区域,那么最简单的方法就是采用RGB色差。
例如在花束中提取红色的花瓣,就可以采用R-G分量差(目标为红色,干扰为G分量),或者,在土壤表面提取绿色秧苗,可以采用G-R-B分量差(G占2份,土壤可能
存在R,B分量干扰),下图为提取结果:
如果遇到更复杂的情况,可以根据目标颜色与干扰颜色设计合适的分量差。
HSI分量灰度化:
H、S、I分别表示色调、饱和度、明度。色调指日常所说的颜色(红,白,黑等),饱和度则表示颜色的鲜艳程度,值越大越鲜艳,明度则是颜色的明亮
程度。这三种属性可以用两个椎体表示,其中明度是竖直中心轴,在竖直方向上,明度不同;每个明度对应一个横截面,用极坐标表示H,S,H为角度,S为模长。
HSI模型如图所示:
我们可以将RGB转为HSI,相关公式有很多种,各有特点,下面介绍其中一种:
rgb_min=min(r,g,b)
rgb_max=max(r,g,b)
I=rgb_max
S=(rgb_max-rgb_min)/rgb_max
if r==rgb_max
H=abs(g-b)/(rgb_max-rgb_min)/3
if g==rgb_max
H=1/3+abs(r-b)/(rgb_max-rgb_min)/3
if b==rgb_max
H=2/3+abs(r-g)/(rgb_max-rgb_min)/3
如此计算所得的H范围为[0,1),S范围为[0,1),I范围[0,255]。HSI分量灰度图如下:
明度分量与一般灰度化效果差不多(可能灰度化可能是基于明度的),有时候利用饱和度与色调灰度号的图像进行提取会便利很多,如下图是基于饱和度的二值提取
(一般如果要基于颜色提取的化采用RGB分量色差比较好,毕竟如果要获取较精准的饱和度信息,所用公式会比上面的复杂):
由于背景的饱和度较低,而目标饱和度高,而且目标由多种颜色组成,这样如果直接基于明度的灰度化不可能提取到整个花束,而通过饱和度提取的效果就非常棒。
另外,也可以将HSI组合起来使用,使得特征更明显,例如可以用饱和度与色调消除红眼现象,具体基于HSI的算法这里就不探究了!
以上相关matlab仿真测试代码如下:
%RGB分量差提取 imga=imread('flower.jpg'); imgb=imread('soil.jpg'); imga2=uint8(zeros(300,300)); imgb2=uint8(zeros(300,300)); for i=1:300 for j=1:300 r=imga(i,j,1); g=imga(i,j,2); if (r>g) imga2(i,j)=uint8(r-g); else imga2(i,j)=0; end end end for i=1:300 for j=1:300 r=imgb(i,j,1); g=imgb(i,j,2); b=imgb(i,j,3); if 2*uint16(g)>(uint16(r)+uint16(b)) imgb2(i,j)=uint8(2*uint16(g)-uint16(r)-uint16(b)); else imgb2(i,j)=0; end end end imga2=imbinarize(imga2,60/255); imgb2=imbinarize(imgb2,40/255); subplot(2,2,1); imshow(imga); title('原图'); subplot(2,2,2); imshow(imga2); title('R-G分量差提取红色部分'); subplot(2,2,3); imshow(imgb); title('原图'); subplot(2,2,4); imshow(imgb2); title('G-R-B分量差提取绿色部分');
%RGB转HSI模型 function myhsvdisplay(file) rgb=imread(file); [sizex,sizey,~]=size(rgb); hsv_v=uint8(zeros(sizex,sizey)); hsv_s=double(zeros(sizex,sizey)); hsv_h=double(zeros(sizex,sizey)); for i=1:sizex for j=1:sizey r=rgb(i,j,1); g=rgb(i,j,2); b=rgb(i,j,3); rgb_min=min([r,g,b]); rgb_max=max([r,g,b]); hsv_v(i,j)=rgb_max; hsv_s(i,j)=(double(rgb_max)-double(rgb_min))/double(rgb_max); if r==rgb_max hsv_h(i,j)=abs( double(g)-double(b))/(double(rgb_max)-double(rgb_min))/double(3); elseif g==rgb_max hsv_h(i,j)=double(1/3)+abs(double(g)-double(b))/(double(rgb_max)-double(rgb_min))/double(3); else hsv_h(i,j)=double(2/3)+abs(double(g)-double(b))/(double(rgb_max)-double(rgb_min))/double(3); end end end subplot(2,2,1); imshow(rgb); title('rgb原图'); subplot(2,2,2); imshow(hsv_v); title('明度信号'); subplot(2,2,3); imshow(hsv_s); title('饱和度信号'); subplot(2,2,4); imshow(hsv_h); title('色调信号'); end
%利用饱和度提取 function sbinarize(file) imga=imread(file); [~,hsv_s,hsv_v]=rgb2hsv(imga); sbin=imbinarize(hsv_s,80/255); vbin=imbinarize(hsv_v,130/255); subplot(1,3,1); imshow(imga); title('原图'); subplot(1,3,2); imshow(sbin); title('饱和度提取'); subplot(1,3,3); imshow(vbin); title('明度提取'); end