CalcBackProjectPatch有两种用法:当采样窗口小于目标时,作为区域检测器,当采样窗口和目标窗口一般大时,作为目标检测器。
CalcBackProjectPatch
用直方图比较来定位图像中的模板
void cvCalcBackProjectPatch( IplImage** image, CvArr* dst, CvSize patch_size, CvHistogram* hist, int method, double factor );
-
image
- 输入图像 (可以传递 CvMat** ) dst
- 输出图像. patch_size
- 扫描输入图像的补丁尺寸 hist
- 直方图 method
- 比较方法,传递给 cvCompareHist (见该函数的描述). factor
- 直方图的归一化因子,将影响输出图像的归一化缩放。如果为 1,则不定。 /*归一化因子的类型实际上是double,而非float*/
函数 cvCalcBackProjectPatch 通过输入图像补丁的直方图和给定直方图的比较,来计算反向投影。提取图像在 ROI 中每一个位置的某种测量结果产生了数组 image. 这些结果可以是色调, x 差分, y 差分, Laplacian 滤波器, 有方向 Gabor 滤波器等中 的一个或多个。每种测量输出都被划归为它自己的单独图像。 image 图像数组是这些测量图像的集合。一个多维直方图 hist 从这些图像数组中被采样创建。最后直方图被归一化。直方图 hist 的维数通常很大等于图像数组 image 的元素个数。
在选择的 ROI 中,每一个新的图像被测量并且转换为一个图像数组。在以锚点为“补丁”中心的图像 image 区域中计算直方图 (如下图所示)。用参数 norm_factor 来归一化直方图,使得它可以与 hist 互相比较。计算出的直方图与直方图模型互相比较, (hist 使用函数 cvCompareHist ,比较方法是 method=method). 输出结果被放置到概率图像 dst 补丁锚点的对应位置上。这个过程随着补丁滑过整个 ROI 而重复进行。迭代直方图的更新可以通过在原直方图中减除“补丁”已复盖的尾象素点或者加上新复盖的象素点来实现,这种更新方式可以节省大量的操作,尽管目前在函数体中还没有实现。
Back Project Calculation by Patches
举例,采样窗口小于目标:
原始图形:
检测区域:
代码:
/*
区域检测
*/
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
void dobackProject2(IplImage* img)
{
IplImage* patch = cvLoadImage("ad.gif");
IplImage* hsv = cvCreateImage(cvGetSize(patch), 8, 3);
cvCvtColor(patch,hsv,CV_BGR2HSV);
IplImage* h_plane = cvCreateImage(cvGetSize(patch), 8, 1);
IplImage* s_plane = cvCreateImage(cvGetSize(patch), 8, 1);
IplImage* v_plane = cvCreateImage(cvGetSize(patch), 8, 1);
cvSplit(hsv, h_plane, s_plane, v_plane, 0);
IplImage* planes[] = {h_plane, s_plane};
//设置直方图每个灰度级的数目
int h_bins = 30;
int s_bins = 32;
int hist_size[] = {h_bins, s_bins};
float h_ranges[] = {0, 180};
float s_ranges[] = {0, 255};
float* ranges[] = {h_ranges, s_ranges};
CvHistogram* hist = cvCreateHist(2,hist_size, CV_HIST_ARRAY, ranges);
cvCalcHist(planes, hist);
cvNormalizeHist(hist,1);
//目标图像
IplImage* img_hsv = cvCreateImage(cvGetSize(img),8,3);
cvCvtColor(img, img_hsv, CV_BGR2HSV);
IplImage* h_planei = cvCreateImage(cvGetSize(img), 8, 1);
IplImage* s_planei = cvCreateImage(cvGetSize(img), 8, 1);
IplImage* v_planei = cvCreateImage(cvGetSize(img), 8, 1);
cvSplit(img_hsv, h_planei, s_planei, v_planei, 0);
IplImage* planesi[] = {h_planei, s_planei};
int iwidth = img->width - patch->width + 1;
int iheight = img->height - patch->height + 1;
IplImage* dst = cvCreateImage(cvSize(iwidth, iheight), 32, 1);
//利用相关法
cvCalcBackProjectPatch(planesi,dst,cvSize(patch->width, patch->height), hist,CV_COMP_CORREL,1);
cvNamedWindow("dst",1);
cvShowImage("dst", dst);
double minv;
double maxv;
CvPoint minl;
CvPoint maxl;
cvMinMaxLoc(dst, &minv,&maxv,&minl,&maxl,NULL);
cvRectangle(img,cvPoint(maxl.x, maxl.y),cvPoint((maxl.x+patch->width),(maxl.y + patch->height)),CV_RGB(255,0,0),1);
cvNamedWindow("match",1);
cvShowImage("match",img);
cvWaitKey(0);
}
输出结果:
参考:
http://wiki.opencv.org.cn/index.php/Cv%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86#CompareHist