直方图匹配-Opencv种cvCalcBackProject的理解

 

转自:http://blog.163.com/chenliangren@126/blog/static/168305659201071711434658/

示例可看本博客:http://blog.163.com/chenliangren@126/blog/static/168305659201072761518425/

另外,可看http://wenku.baidu.com/view/ff8503da50e2524de5187e99.html([]Learning OpenCVTemplateMatching )了解更详细的资料。

直方图的对比


    OpenCv提供了5种对比直方图的方式:CORREL(相关)、CHISQR(卡方)、INTERSECT(相交)、BHATTACHARYYAEMD(最小工作距离),其中CHISQR速度最快,EMD速度最慢且有诸多限制,但是EMD的效果最好。世界总是充满了矛盾,而我们的工作就是化解矛盾(  需要注意的是:EMD方式要求先将直方图转换成矩阵:

对比方法:对于直方图的相关和相交对比,结果值越大(即亮度较高)的地方表示匹配程度越高;
对于直方图的卡方、BhattacharyyaEMD对比,结果值越小(即越黑暗)的地方表示匹配程度越高。

 

直方图的反向投影

CalcBackProject

计算反向投影

void cvCalcBackProject( IplImage** image, CvArr* back_project, const CvHistogram* hist );

image

输入图像 (也可以传递 CvMat** ).

back_project

反向投影图像,与输入图像具有同样类型.

hist

直方图

函数 cvCalcBackProject 计算直方图的反向投影对于所有输入的单通道图像同一位置的象素数组,该函数根据相应的象素数组(RGB),放置其对应的直方块的值到输出图像中。用统计学术语,输出图像象素点的值是观测数组在某个分布(直方图)下的概率。 例如,为了发现图像中的红色目标,可以这么做:

1 对红色物体计算色调直方图,假设图像仅仅包含该物体。则直方图有可能有极值,对应着红颜色。

2 对将要搜索目标的输入图像,使用直方图计算其色调平面的反向投影,然后对图像做阈值操作。

3 在产生的图像中发现连通部分,然后使用某种附加准则选择正确的部分,比如最大的连通部分。

这是 Camshift 彩色目标跟踪器中的一个逼进算法,除了第三步,CAMSHIFT 算法使用了上一次目标位置来定位反向投影中的目标。

(注:对cvCalcBackProject的说明引用自http://www.opencv.org.cn/index.php/Cv%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86#CompareHist


1.反向投影的作用是什么?
    反向投影用于在输入图像(通常较大)中查找特定图像(通常较小或者仅1个像素,以下将其称为模板图像)最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。
2.反向投影如何查找(工作)?
    查找的方式就是不断的在输入图像中切割跟模板图像大小一致的图像块,并用直方图对比的方式与模板图像进行比较。

假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
1)从输入图像的左上角(0,0)开始,切割一块(0,0)(10,10)的临时图像;
2)生成临时图像的直方图;
3)用临时图像的直方图和模板图像的直方图对比,对比结果记为c
4)直方图对比结果c,就是结果图像(0,0)处的像素值;
5)切割输入图像从(0,1)(10,11)的临时图像,对比直方图,并记录到结果图像;
6)重复(1)~(5)步直到输入图像的右下角。

3.反向投影的结果是什么?
    反向投影的结果包含了:以每个输入图像像素点为起点的直方图对比结果。可以把它看成是一个二维的浮点型数组,二维矩阵,或者单通道的浮点型图像。
4.特殊情况怎么样?
    如果输入图像和模板图像一样大,那么反向投影相当于直方图对比。如果输入图像比模板图像还小,直接罢工~~。
5.使用时有什么要注意的地方?
    需要注意的地方比较多,我们对照反向投影函数来说:
    (void cvCalcBackProjectPatch
        IplImage** image,   /*输入图像:是一个单通道图像数组,而非实际图像*/
        CvArr* dst,         /*输出结果:是一个单通道32位浮点图像,它的宽度为W-w+1,高度为H-h+1,这里的WH是输入图像的宽度和高度,wh是模板图像的宽度和高度*/
        CvSize patch_size,  /*模板图像的大小:宽度和高度*/
        CvHistogram* hist,  /*模板图像的直方图:直方图的维数和输入图像的个数相同,并且次序要一致;例如:输入图像包含色调和饱和度,那么直方图的第0维是色调,第1维是饱和度*/
        int method,         /*对比方式:跟直方图对比中的方式类似,可以是:CORREL(相关)、CHISQR(卡方)、INTERSECT(相交)、BHATTACHARYYA*/
        float factor        /*归一化因子,一般都设置成1,否则很可能会出错;中文、英文以及各路转载的文档都错了,这个参数的实际类型是double,而非float我看了源代码才搞定这个地方*/
    );
    还有最需要注意的地方:这个函数的执行效率非常的低,在使用之前尤其需要注意图像的大小,直方图的维数,对比方式。如果说对比单个直方图对现在的电脑来说是清风拂面,那么反向投影是狂风海啸。对于1010x1010RGB输入图像,10x10的模板图像,需要生成1百万次3维直方图,对比1百万次3维直方图。

(注:对void cvCalcBackProjectPatch的使用引用自http://www.cnblogs.com/xrwang/archive/2010/02/04/HowToUseHistogram.html

直方图匹配是一用于调整图像颜色分布的方法,使得两幅图像的直方图变得相似。在OpenCV中,可以使用`cv::equalizeHist()`函数来实现直方图均衡化,从而实现直方图匹配。 下面是一个使用OpenCV C++实现直方图匹配的示例代码: ```cpp #include <opencv2/opencv.hpp> int main() { // 读取输入图像 cv::Mat image = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE); // 读取目标图像 cv::Mat target = cv::imread("target.jpg", cv::IMREAD_GRAYSCALE); // 计算输入图像的直方图 cv::Mat hist; cv::calcHist(&image, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange); // 计算目标图像的直方图 cv::Mat targetHist; cv::calcHist(&target, 1, 0, cv::Mat(), targetHist, 1, &histSize, &histRange); // 计算输入图像的累积直方图 cv::Mat cumHist; cv::normalize(hist, cumHist, 0, 255, cv::NORM_MINMAX); // 计算目标图像的累积直方图 cv::Mat targetCumHist; cv::normalize(targetHist, targetCumHist, 0, 255, cv::NORM_MINMAX); // 创建输出图像 cv::Mat result = cv::Mat::zeros(image.size(), image.type()); // 进行直方图匹配 for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { int intensity = image.at<uchar>(i, j); result.at<uchar>(i, j) = cv::saturate_cast<uchar>(targetCumHist.at<float>(intensity)); } } // 显示结果图像 cv::imshow("Result", result); cv::waitKey(0); return 0; } ``` 请注意,上述代码中的`input.jpg`和`target.jpg`分别代表输入图像和目标图像的文件名。你需要将代码中的这两个文件名替换为你自己的图像文件名。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值