opencv下通过模板匹配进行人体跟踪

本人学习opencv了半个月,学到模板匹配函数时灵感一动,写出了这个模板匹配的函数。特此,将我的灵感奉献给大家。废话不多说,代码贴上。

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <conio.h>
#include <iostream>
#include <cxcore.h>
#include <opencv2/core/core.hpp>
#include "math.h"


using namespace std;
using namespace cv;


#define meichao   "未超界"
#define chao_zuo  "摄像头向左移动"
#define chao_you  "摄像头向右移动"
#define chao_qian "摄像头向前移动"
#define chao_hou  "摄像头向后移动"


#define qian_zuo   10
#define qian_you   11
#define hou_zuo    12
#define hou_you    13
#define qian       14
#define hou        15
//归一化函数,是使没有可比型的数据变得具有可比型,同时又保持相比较的连个数据的相对关系
//都一个参数:输入数组
//第二个参数:输出数组,支持原地运算
//第三个参数:模式最小值
//第四个参数:模式最大值
//第五个参数:归一化类型
//第六个参数:当其为负数时,输出数组类型与原数组相同,否则输出数组与输入数组只是通道数相同,type=CV_MAT_DEPTH(dypte)


#define WINDOW_NAME1 "[原始窗口]"
#define WINDOW_NAME2 "[效果窗口]"
#define WINDOW_NAME3 "[效果窗口2]"
#define WINDOW_NAME4 "[原始窗口4]"


IplImage* pFrame=NULL;
CvCapture* pCapture=cvCreateCameraCapture(0);


Mat g_srcImage;
Mat g_srcImage2;


Mat g_templateImage;


Mat g_resultImage;
Mat g_resultImage2;


int g_nMatchMethod;
int g_nMaxTrackbarNum=5;
int fangxiang;
String jiexian;
Mat srcImage;
Mat srcImage2;
int resultImage_cols;
int resultImage_rows;
int resultImage_cols2;
int resultImage_rows2;
double minValue;double maxValue;Point minLocation;Point maxLocation;
Point mathLocation;
double minValue2;double maxValue2;Point minLocation2;Point maxLocation2;
Point mathLocation2;
int zhou_x;
int zhou_y;
char c;
//int biaozhun_x;
//int biaozhun_y;


void on_Matching(int,void*);
//--------------------------------[main()函数]------------------------------------------------------------------
//         描述:控制台应用的入口函数,我们程序都从这里开始
//----------------------------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{

/*
namedWindow(WINDOW_NAME1,CV_WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME2,CV_WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME3,CV_WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME4,CV_WINDOW_AUTOSIZE);
*/
cvNamedWindow("video",1);
while(1)
{
pFrame=cvQueryFrame(pCapture);
if(!pFrame)break;
cvShowImage("video",pFrame);
   c=waitKey(33);
if(c==27){break;}
if(c==49)
{
cvSaveImage("tuxiang_1.jpg",pFrame);
Mat xianshi_1(pFrame);
imshow("xianshi_1",xianshi_1);
waitKey(3000);
//continue;
}
if(c==50)
{
cvSaveImage("tuxiang_2.jpg",pFrame);
Mat xianshi_2(pFrame);
imshow("xianshi_2",xianshi_2);
waitKey(3000);
//continue;
}
if(c==13)
{
//按1---储存第一次,按2----储存第二次
//格式:640*480
g_srcImage=imread("tuxiang_1.jpg",1);
g_templateImage=imread("1.jpg",1);
g_srcImage2=imread("tuxiang_2.jpg",1);
//printf("src1的x总长,y总长:%d    %d\r\n",g_srcImage.cols,g_srcImage.rows);
//printf("src2的x总长,y总常;%d    %d\r\n",g_srcImage2.cols,g_srcImage2.rows);
createTrackbar("方法",WINDOW_NAME1,&g_nMatchMethod,g_nMaxTrackbarNum,on_Matching);
on_Matching(0,0);
waitKey(0);
}
}

return 0; 
}


void on_Matching(int,void*)
{

g_srcImage.copyTo(srcImage);
srcImage2.copyTo(srcImage);
//这些数据用于输出
    resultImage_cols=g_srcImage.cols-g_templateImage.cols+1;
    resultImage_rows=g_srcImage.rows-g_templateImage.rows+1;


    resultImage_cols2=g_srcImage2.cols-g_templateImage.cols+1;
    resultImage_rows2=g_srcImage2.cols-g_templateImage.cols+1;


g_resultImage.create(resultImage_cols,resultImage_rows,CV_32FC1);
g_resultImage2.create(resultImage_cols2,resultImage_rows2,CV_32FC1);


matchTemplate(g_srcImage,g_templateImage,g_resultImage,g_nMatchMethod);
matchTemplate(g_srcImage2,g_templateImage,g_resultImage2,g_nMatchMethod);
normalize(g_resultImage2,g_resultImage2,0,1,NORM_MINMAX,-1,Mat());
normalize(g_resultImage,g_resultImage,0,1,NORM_MINMAX,-1,Mat());
    

minMaxLoc(g_resultImage,&minValue,&maxValue,&minLocation,&maxLocation,Mat());
minMaxLoc(g_resultImage2,&minValue2,&maxValue2,&minLocation2,&maxLocation2,Mat());
if(g_nMatchMethod==CV_TM_SQDIFF||g_nMatchMethod==CV_TM_SQDIFF_NORMED)
{
mathLocation=minLocation;
mathLocation2=minLocation2;
}
else
{
mathLocation=maxLocation;
mathLocation2=maxLocation2;
}


//rectangle(srcImage,mathLocation,Point(mathLocation.x+g_templateImage.cols,mathLocation.y+g_templateImage.rows),Scalar(0,0,255),2,8,0);
//rectangle(g_resultImage,mathLocation,Point(mathLocation.x+g_templateImage.cols,mathLocation.y+g_templateImage.rows),Scalar(0,0,255),2,8,0);

//rectangle(srcImage,minLocation,maxLocation,Scalar(0,0,255),2,8,0);
//rectangle(g_resultImage,minLocation,maxLocation,Scalar(0,0,255),2,8,0);
zhou_x=mathLocation2.x-mathLocation.x;
zhou_y=mathLocation2.y-mathLocation.y;
 
fangxiang=0;

if(zhou_x>=0&&zhou_y>=0)
{
fangxiang=qian_you;
//这里是重点
if(zhou_x>=zhou_y*1.3&&zhou_x<=zhou_y*1.9)
{
fangxiang=qian;
}
}
if(zhou_x>=0&&zhou_y<0)
{
fangxiang=hou_you;
if(zhou_x>=zhou_y*1.3&&zhou_x<=zhou_y*1.9)
{
fangxiang=hou;
}
}
if(zhou_x<0&&zhou_y>=0)
{
fangxiang=qian_zuo;
if(zhou_x>=zhou_y*1.3&&zhou_x<=zhou_y*1.9)
{
fangxiang=qian;
}
}
if(zhou_x<0&&zhou_y<0)
{
fangxiang=hou_zuo;
//这里是重点
if(zhou_x>=zhou_y*1.3&&zhou_x<=zhou_y*1.9)
{
fangxiang=hou;
}
}




//只需要第一次在中间即可420,164
if(mathLocation.x>=410)
{
jiexian=chao_you;
printf("\r\n摄像头应该向左移动\r\n");
}
if(mathLocation.x<=190)
{
jiexian=chao_zuo;
printf("\r\n摄像头应该向右移动\r\n");
}
/*
imshow(WINDOW_NAME1,srcImage);
imshow(WINDOW_NAME4,srcImage2);
imshow(WINDOW_NAME2,g_resultImage);
imshow(WINDOW_NAME3,g_resultImage2);
*/

printf("\r\n");
printf("你本次移动的方向为:%d\r\n",fangxiang);
printf("检测点的坐标_X,检测点的坐标_Y: %d    %d\r\n",mathLocation.x,mathLocation.y);
printf("检测点2的坐标_X,检测点2的坐标_Y: %d    %d\r\n",mathLocation2.x,mathLocation2.y);

remove("2.jpg");
remove("3.jpg");


}



为了方便新手学习我讲解一下这个算法,首先我调用摄像头,并且等待键盘敲入的值。如果是1,则保存这一帧所截取的图像,等待3s并且回归到摄像头显示。如果是2,则截取这一帧所截取的图像,等待三秒并退出。者两张图像保存的名字叫做“2.jpg”与“3.jpg”。者两张图片图片就是我们模板匹配的背景。然后我们按回车键

就进行模板匹配的算法处理,并且进行路径比较,和定位以计算出人移动的方向。


但是请注意,我们的“1.jpg”是你所追踪的人的先要特征的截图。比如我外套没有拉起来,露出来的中间的衬衣就是我模板匹配的标本。然后在匹配之前我么你要进行归一化处理。归一化处理函数是为了使两个模板有更好的相似性,提高匹配精度。


别人的模板匹配算法用了六个参数来定位不同背景下哪个参数好用。但我们只用者6个参数中的一个来完成我么你的算法,因为之前我单独使用者6个参数进行比较,得到一个符合我的参数,同学们可以自行尝试这个函数来获得对自己来说效果更好的参数。

在模板匹配的结果会获得一个mathlocation点,这个点非常重要,它影响了们后面的追踪程序。我们的摄像头

正俯着人,那么可以计算这个点的移动方向来判断这个人的左右移动方向,同时计算其前后方向来判断这个人的前后移动方向。这里的坐标是向右为正,向上为正。这里我们先测量了照片的大小,并且加入了摄像头拍摄的人是否在边界的判断,并传输信息向左移动或者向右移动。

经本人实践检验,在衣服不改变的情况下,算法可以实现对人体移动方向的判断。

如有对此感兴趣的人请留言讨论。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值