meanshift算法学习(一):opencv中的calcBackProject
来源:互联网 发布:如何学好高中语文知乎 编辑:程序博客网 时间:2024/05/03 14:02
0.前言
在看《opencv2计算机视觉编程手册》的第四章时,看到了书中利用opencv提供的meanshift算法实现指定区域的跟踪,感觉很神奇,就相对深入的了解了下。不过这里没有直接上来讲meanshift,而是opencv的calcBackProject()函数。为啥呢,因为书中的例程首先利用它计算反投影矩阵用作meanshift算法的输入。
1.反投影直方图及原理
直方图是图像的一个重要内容,可以作为图像的一个描述特征(当该图像有明显的纹理时效果更佳)。这里我们有图像B和图像A且图像B中包含图像A或类似于图像A的区域,那么如何确定它在B中的确切位置?一种做法就是,计算图像A的直方图,且假定它能够有效地代表A(不是适用于所有情况),之后遍历图像B,使用B中每一点像素对应A的直方图中的统计值来替换原像素的值。如此一来,图像B就变成 了相对于A中各个成分的一个分布图,每一点的值越高,就代表他它属于图像A的可能性越大。
2.反投影的代码实现
知道原理后,就可以用代码实现它了,自己写了一个demo来简单的验证,代码如下。
#include <iostream>#include <vector>#include <core/core.hpp>#include <imgproc/imgproc.hpp>#include <highgui/highgui.hpp>#include <opencv2/nonfree/features2d.hpp>#include <features2d/features2d.hpp>#include <legacy/legacy.hpp>using namespace std;using namespace cv;int main(){Mat image = imread("beach.jpg", 0);Mat image_show;image.copyTo(image_show);rectangle(image_show, Rect(360, 55, 40, 50), Scalar(0));imshow("image", image_show);// 选取感兴趣区域Mat ROI = image(Rect(360, 55, 40, 50));int histSize[1];float hranges[2];const float* ranges[1];int channels[1];histSize[0] = 256;hranges[0] = 0.f;hranges[1] = 255.f;ranges[0] = hranges;channels[0] = 0;// 计算感兴趣区域的灰度直方图MatND hist;calcHist(&ROI, 1, channels, Mat(), hist, 1, histSize, ranges);normalize(hist, hist, 1.0);/*Mat result;calcBackProject(&image, 1, channels, hist, result, ranges, 255.0);imshow("result", result);*/double min, max;minMaxLoc(hist, &min, &max);double scale = 255.f/(max - min);Mat result_test(image.size(), CV_8UC1);for(int i = 0; i < result_test.rows; i++){for(int j = 0; j < result_test.cols; j++){int gray = image.at<unsigned char>(i,j);// 使用直方图中的统计值相对大小代替原图的灰度值result_test.at<unsigned char>(i,j) = (int)((hist.at<float>(gray) - min)*scale);}}imshow("result_test", result_test);waitKey();return 0;}
运行效果如下所示,图1中黑色边框是我们的感兴趣区域,图2则是代表感兴趣区域可能出现的可能性表现(颜色越深,可能性越小)。结果我们看到有很多高可能性的区域,部分原因就是因为黑色边框选择的区域在原图中不具有什么代表性。图1
图2
3.calcBackProject()函数
当然上一部分中的反投影计算部分局限性很大,毕竟图像的类型、深度、通道数有很多。但是opencv毕竟是大牛们的作品,opencv提供的calcBackProject()函数能够实现多种类型图像的反投影计算,原理和第二部分大致相同。具体使用我就不提了,书上和网上有很多例程,贴一张用calcBackProject()计算得到的反投影效果,见图3。可以看到和图2相比,区别就在于灰度的分布范围,这个是可以人为控制的。
图3
4.提升反投影效果
图2或者图3中的效果并不理想,我们拿到后很难确定感兴趣区域的具体位置。部分原因是我们把彩色图转为了灰度图进行的后续计算,丢失了一些色彩信息。针对这个,书中提了一种改进方法,针对彩色图,转换到HSV空间,在计算直方图和反投影时,忽略低饱和度(S)的像素。书中提供了检测猴子脸部的例子,自己比较了下该方法和原始方法的效果差异,是有比较明显的提升。图4中寻找左边猴子脸部在第二张图片的位置,"result"和"result_hsv"分别是使用基本方法(原图转为灰度图后直接计算反投影)和使用书中例程计算得到的结果,对比可以发现后者效果明显好很多,后续使用它作为输入进行位置的精确计算时难度会下降很多。
5.其他
至此,我们只得到了猴子脸部的一张“分布概率”图,并不知道它的确切位置。那么如何得到最后的位置呢?当然我可以遍历这样图得到最大值的点,然后把该点作为结果。方法简单粗暴,但是复杂度并不好。然后meanshift算法就出现了,它就可以实现结果的快速迭代优化而不是傻兮兮的遍历。终于讲到这了。。不过有关这方面的内容,我要放到下一篇文章了点击打开链接
阅读全文
1 0
- meanshift算法学习(一):opencv中的calcBackProject
- meanshift算法学习(二):opencv中的meanshift
- opencv学习(三十九)之反向投影calcBackProject()
- meanshift算法学习(三):自己实现meanshift
- 基于opencv的meanshift算法的初步学习
- MeanShift算法C++解析(一)
- MeanShift算法(一)
- opencv中的meanshift图像分割
- MeanShift算法学习
- Meanshift算法学习笔记
- Opencv学习笔记(二)meanshift之我见
- Python+OpenCV学习(13)---meanshift目标跟踪
- 机器学习算法原理与实践(二)、meanshift算法图解以及在图像聚类、目标跟踪中的应用
- 机器学习算法原理与实践(二)、meanshift算法图解以及在图像聚类、目标跟踪中的应用
- 基于Opencv的MeanShift跟踪算法实现
- MeanShift和Camshift算法实现 Opencv
- 基于Opencv的MeanShift跟踪算法实现
- 基于Opencv的MeanShift跟踪算法实现
- oracle数据库(范式)
- Win32实现DES加密算法
- 第九周项目2-二叉树递归遍历
- Java数据结构与算法解析(八)——伸展树
- 爬取广州链家租房信息,并用tableau进行数据分析
- meanshift算法学习(一):opencv中的calcBackProject
- hive 优化 控制 map 和 reduce的数量
- Callback 与 Promise 间的桥梁 —— promisify
- HDU6143 Killer Names(数论)
- DNS协议概述
- 字符串对象方法(API)
- Java数据结构与算法解析(九)——B树
- MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】
- IO流的基础2