反向投影
最近在学习opencv, 想做一个检测目标的东西出来,于是便出来了下文。
期望目标是,在图片中能够讲特定目标识别,并报告出位置。
第一反应是用模板匹配,可是效果很不理想。模板图片是从检测图片中截取出来的,可经常右匹配不准的情况。因为图片中类似的特征很多,如果模板不具有一个很强的特征,那么很可能局部有与此更相似的区域出现,导致匹配错误。它严重依赖于模板特性,如果在某些条件下不适宜提供模板的情况下,就没法继续。同时,匹配的时间也较长。
当然,还有另外的路子。
直方图匹配。它的思想是,对于一个目标的图片,提取出H分量,并计算该分量直方图,并用此与待匹配的图片作反向投影,这样便将目标从待匹配图片中“提取”出来(准确来讲是连通起来,对我们的肉眼来讲,就等于“提取”)。尤其适用与对颜色比较敏感的目标。
为什么反向投影可以将目标“提取”出来?因为假定待检测图片中,目标的H分量出现的概率最大(如果不能保证这一点,得到的反向投影噪音会很大)。
反向投影的作用在于,对于源图像中的H分量(灰度图)中的每一像素,用给定的直方图(目标图像)中对应的该区间的 频数 来替换 该像素的灰度值。这样,经过反向投影后,源图像中的包含有目标的区域像素会被替换为频数,他们是相等的,等于模板目标中相等的H值对应的频数。这样具有相同肤色的像素点会被连通起来,连成一片,闪闪发亮或者集体沉默。而对于这些像素点,我们有高概率认为他们是模板目标中的H值(概率有多高?从模板目标的H值对应频数与总数计算来的)
1 #include <iostream>
2 #include <opencv2/imgproc/imgproc.hpp>
3 #include <opencv2/highgui/highgui.hpp> 4 #include <opencv2/video/tracking.hpp> 5 6 7 using namespace std; 8 using namespace cv; 9 10 11 int histSize = 180; 12 float hue_range[] = { 0, 180 }; 13 const float* ranges = { hue_range }; 14 15 int split_hue(Mat &src,Mat &hue) 16 { 17 Mat hsv; 18 19 cvtColor( src, hsv, CV_BGR2HSV ); 20 hue.create( hsv.size(), hsv.depth() ); 21 22 int ch[] = { 0, 0 }; 23 mixChannels( &hsv, 1, &hue, 1, ch, 1 ); 24 25 return 0; 26 } 27 28 int get_hist(const string file,Mat &hist) 29 { 30 Mat tpl,hue; 31 32 tpl = imread(file, 1 ); 33 split_hue(tpl,hue); 34 35 calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false ); 36 normalize( hist, hist, 0, 250, NORM_MINMAX, -1, Mat() ); 37 38 return 0; 39 } 40 41 int main(int args,char **argv) 42 { 43 Mat tpl,src,hsv1,hsv2,hue,hue2; 44 Mat hist,backproj; 45 46 //获取模板图像hue分量直方图 47 get_hist("../pic/tt.jpg",hist); 48 49 //源图像hue分量 50 src = imread("../pic/fin33.jpg",1); 51 split_hue(src,hue); 52 53 //源图像的hue分量图 54 namedWindow("hue", CV_WINDOW_NORMAL ); 55 imshow( "hue",hue); 56 57 /// 计算反向投影 58 calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true ); 59 60 namedWindow("BackProj", CV_WINDOW_NORMAL ); 61 imshow( "BackProj", backproj ); 62 63 //反向投影threshed,阈值为2,将一些噪音点去除 64 threshold(backproj,backproj , 2, 250, THRESH_BINARY); 65 66 namedWindow("threshedProj", CV_WINDOW_NORMAL ); 67 imshow( "threshedProj", backproj );
76 waitKey(0); 77 78 }
模板图像,定义肤色信息

源图像

hue分量

反向投影,可以看到手部集聚了众多的白点

threshed后,手部信息更加明显

但是仍然右问题,图像的左上角仍然有众多的噪点,经过阈值化,仍然不能消除。下一步准备使用轮廓的方式作进一步处理

浙公网安备 33010602011771号