模板匹配是一种在图像中定位目标的方法,通过把输入图像在实际图像上逐像素点滑动,计算特征相似性,以此来判断当前滑块图像所在位置是目标图像的概率

在Opencv中,模板匹配定义了6种相似性对比方式:

CV_TM_SQDIFF 平方差匹配法:计算图像像素间的距离之和,最好的匹配是0,值越大,是目标的概率就越低。

    CV_TM_CCORR 相关匹配法:一种乘法操作;数值从小到大,匹配概率越来越高。

    CV_TM_CCOEFF 相关系数匹配法:从-1到1,匹配概率越来越高。

    CV_TM_SQDIFF_NORMED 归一化平方差匹配

    CV_TM_CCORR_NORMED 归一化相关匹配

    CV_TM_CCOEFF_NORMED 归一化相关系数匹配

视频文件中移动物体的跟踪,本质上还是图像上目标跟踪,可以使用模板匹配方法,实现简单的匹配跟踪效果,只不过模板匹配要逐像素移动去匹配目标图像,计算量大,实时性差。

以下代码实现基于模板匹配的目标跟踪。通过鼠标单击在视频上画出矩形,定义需要跟踪的目标,在匹配到目标的时候,用目标图像刷新输入图像:

#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include<iostream> using namespace cv;
using namespace std; Mat image; //视频流
Mat imageCopy; //绘制矩形框时用来拷贝原图的图像
Mat rectImage; //子图像
bool leftButtonDownFlag=false; //左键单击后视频暂停播放的标志位
Point originalPoint; //矩形框起点
Point processPoint; //矩形框终点 int resultRows; //模板匹配result的行
int resultcols; //模板匹配result的列
Mat ImageResult; //模板匹配result
double minValue; //模板匹配result最小值
double maxValude; //模板匹配result最大值
Point minPoint; //模板匹配result最小值位置
Point maxPoint; //模板匹配result最大值位置
int frameCount=0; //帧数统计 void onMouse(int event,int x,int y,int flags ,void* ustc); //鼠标回调函数 int main(int argc,char*argv[])
{
VideoCapture video(argv[1]);
double fps=video.get(CV_CAP_PROP_FPS); //获取视频帧率
double pauseTime=1000/fps; //两幅画面中间间隔
namedWindow("Man",0);
setMouseCallback("Man",onMouse);
while(true)
{
if(!leftButtonDownFlag) //鼠标左键按下绘制矩形时,视频暂停播放
{
video>>image;
frameCount++; //帧数
}
if(!image.data||waitKey(pauseTime+30)==27) //图像为空或Esc键按下退出播放
{
break;
}
if(rectImage.data)
{
ImageResult=Mat::zeros(resultRows,resultcols,CV_32FC1);
matchTemplate(image,rectImage,ImageResult,CV_TM_SQDIFF); //模板匹配
minMaxLoc(ImageResult,&minValue,&maxValude,&minPoint,&maxPoint,Mat()); //最小值最大值获取
rectangle(image,minPoint,Point(minPoint.x+rectImage.cols,minPoint.y+rectImage.rows),Scalar(0,0,255),2);
//更新当前模板匹配的模板
Mat resultImage=image(Rect(minPoint,Point(minPoint.x+rectImage.cols,minPoint.y+rectImage.rows)));
rectImage=resultImage.clone();
//当前帧数输出到视频流
stringstream ss;
ss<<frameCount;
string h="Current frame is: ";
string fff=h+ss.str();
putText(image,fff,Point(50,60),CV_FONT_HERSHEY_COMPLEX_SMALL,2,Scalar(0,0,255),2);
}
imshow("Man",image);
}
return 0;
} //*******************************************************************//
//鼠标回调函数
void onMouse(int event,int x,int y,int flags,void *ustc)
{
if(event==CV_EVENT_LBUTTONDOWN)
{
leftButtonDownFlag=true; //标志位
originalPoint=Point(x,y); //设置左键按下点的矩形起点
processPoint=originalPoint;
}
if(event==CV_EVENT_MOUSEMOVE&&leftButtonDownFlag)
{
imageCopy=image.clone();
processPoint=Point(x,y);
if(originalPoint!=processPoint)
{
//在复制的图像上绘制矩形
rectangle(imageCopy,originalPoint,processPoint,Scalar(0,0,255),2);
}
imshow("Man",imageCopy);
}
if(event==CV_EVENT_LBUTTONUP)
{
leftButtonDownFlag=false;
Mat subImage=image(Rect(originalPoint,processPoint)); //子图像
rectImage=subImage.clone();
resultRows=image.rows-rectImage.rows+1;
resultcols=image.cols-rectImage.rows+1;
imshow("Sub Image",rectImage);
}
}

框选出的跟踪目标:

跟踪效果:

在目标特征变化不是特别快的情况下,跟踪效果还可以,同时也存在两个问题:

1. 模板匹配的速度很慢:原始视频图像大小是1920*1080的彩色RGB图像,直接拿来目标匹配,在我的机器上消耗时间大约为1s,根本谈不上实时性。优化方向可以考虑原始图像和输入图像都做金字塔缩放,速度提升应该很明显。

2. 存在跟踪漂移:随时更新跟踪目标这种在线跟踪方法,很容易导致跟踪漂移问题,特别是在目标本身的特征变化较大的情况下,严重的还有可能完全跟丢目标,并且永久丢失对目标的跟踪。优化方向可以考虑对历史上检测出的目标图像采用累积权重法生成下一个输入图像。另一个针对完全跟丢的情况,可以对目标匹配的概率设置一个阈值,小于阈值的,可能检测到的是一个跟目标差异很大的物体,不对输入图像做更新。

最新文章

  1. js从数组中随机取出不同的元素
  2. js转盘抽奖
  3. JAVASE02-Unit06: 文件操作——File 、 文件操作—— RandomAccessFile
  4. 网站上点击自定义按钮发起QQ聊天的解决方案
  5. Windows2003 SQL2005解决系统Administrator密码不知道的问题
  6. 删除ecshop登录后台看到的系统信息
  7. 使用modelsim仿真DDR3时编译出错的解决方法
  8. JAVA 面向对象-2-继承(Inheritance)
  9. Debian(Linux)系统目录简单说明
  10. Javascript中布尔运算符的高级应用
  11. ajax多次请求,只执行最后一次的方法
  12. springboot配置swagger2
  13. SAP高可用性(HA)
  14. Android简易实战教程--第二话《两种进度条》
  15. java学习笔记08-switch case语句
  16. Polynomial_0
  17. nginx之location的匹配规则
  18. PHP Backdoor + Reverse Shell on Vulnerable Website
  19. Git:常用命令(二)
  20. 每个成长者,必须学会可以练习 (来自ProcessOn流程图工具作者底部)

热门文章

  1. BZOJ3192: [JLOI2013]删除物品(splay)
  2. arcgis webapp builder 安装试用
  3. do_pj--下拉代码脚本的使用
  4. 让单选input框,不在被选中,添加disabled即可。输入框input的一些技巧
  5. VUE笔记 - 品牌后台 - v-for Splice Some Filter findIndex indexOf 直接return函数结果
  6. 【Codeforces Round #450 (Div. 2) B】Position in Fraction
  7. usr/bin/mysqladmin: refresh failed; error: &amp;#39;Unknown error&amp;#39;
  8. js进阶 13-7 如何实现滑动面板效果
  9. 添加asp.net mvc到现有的asp.net web form 应用程序
  10. Android javaMail使用imap协议接收邮件