cvCalcBackProjectPatch()是用于在被查找图像上查找给定的模版的位置,这也是反向投影的主要用途。具体算法如下:
假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
(1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
(2)生成临时图像的直方图;
(3)用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
(4)直方图对比结果c,就是结果图像(0,0)处的像素值;
(5)切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
(6)重复(1)~(5)步直到输入图像的右下角。
具体看下面例子:
#include<cv.h>
#include<highgui.h>
#include<stdio.h>
int main(int argc,char *argv[])
{
cvNamedWindow("source");
cvNamedWindow("result");
IplImage *src = cvLoadImage(argv[1]);
IplImage *temp = cvLoadImage(argv[2]);
IplImage *src_hsv = cvCreateImage(cvGetSize(src),8,3);
IplImage *temp_hsv = cvCreateImage(cvGetSize(temp),8,3);
cvCvtColor(src,src_hsv,CV_BGR2HSV);
cvCvtColor(temp,temp_hsv,CV_BGR2HSV);
//创建模版直方图
IplImage *temp_h = cvCreateImage(cvGetSize(temp),8,1);
IplImage *temp_s = cvCreateImage(cvGetSize(temp),8,1);
IplImage *temp_v = cvCreateImage(cvGetSize(temp),8,1);
cvSplit(temp_hsv,temp_h,temp_s,temp_v,NULL);
int sizes[] = {30,32,32};
float h_range[] = {0,180};
float s_range[] = {0,255};
float v_range[] = {0,255};
float *ranges[] = {h_range,s_range,v_range};
CvHistogram *hist = cvCreateHist(3,sizes,CV_HIST_ARRAY,ranges,1);
IplImage *temp_planes[] = {temp_h,temp_s,temp_v};
cvCalcHist(temp_planes,hist,0,NULL);
cvNormalizeHist(hist,1);
//进行反向投影
IplImage *src_h = cvCreateImage(cvGetSize(src),8,1);
IplImage *src_s = cvCreateImage(cvGetSize(src),8,1);
IplImage *src_v = cvCreateImage(cvGetSize(src),8,1);
cvSplit(src_hsv,src_h,src_s,src_v,NULL);
IplImage *src_planes[] = {src_h,src_s,src_v};
IplImage *dst = cvCreateImage(cvSize(src->width - temp->width + 1,src->height - temp->height + 1),IPL_DEPTH_32F,1);
cvCalcBackProjectPatch(src_planes,dst,cvGetSize(temp),hist,CV_COMP_CORREL,1);
//找出最匹配的位置
CvPoint max_loc;
cvMinMaxLoc(dst,NULL,NULL,NULL,&max_loc);
max_loc.x += cvRound(temp->width / 2);
max_loc.y += cvRound(temp->height / 2);
cvCircle(src,max_loc,5,CV_RGB(255,0,0),-1);
cvShowImage("source",src);
cvShowImage("result",dst);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvReleaseImage(&src_hsv);
cvReleaseImage(&src_h);
cvReleaseImage(&src_s);
cvReleaseImage(&src_v);
cvReleaseImage(&temp);
cvReleaseImage(&temp_hsv);
cvReleaseImage(&temp_h);
cvReleaseImage(&temp_s);
cvReleaseImage(&temp_v);
cvDestroyWindow("source");
cvDestroyWindow("result");
return 0;
}
运行结果如下:
注意:该函数运行速度比较慢,本程序大概要运行2分钟左右