您的位置:首页 > 移动开发 > Android开发

opencv在Android上实现物体跟踪(7)

2015-01-25 11:21 363 查看


简介

  本章继续在opencv和android平台上,利用opencv的算法来实现对物体的跟踪。


实现步骤


原理介绍

  实现物体跟踪,需要一个用来匹配的模板图像,以及被分析跟踪的原图像或者原视频流。如果被分析的是视频流,也是将它拆分成一帧一帧的图像进行分析。
因此,我们只讨论对一张图像上找到模板图像的做法。

  计算模板匹配方法是,从原图像的左上角开始,从左往右,接着从上往下,每个像素点的位置作为模板图像的做上角位置,接着计算出这个位置,原图像对目标图像的
匹配度,接着新建一张和原图像一样大小的空白图像。将每个点的匹配度存在空白图像对应的像素位置。

  整个计算完了之后,新建的空白图像每个像素点位置,都存好了原图像对应像素点位置对于模板图像的匹配度,匹配度越高的,表示在该点位置,是模板图像的可能性
越高。


opencv匹配度计算

  OpenCV通过函数 matchTemplate 实现了模板匹配算法. 可用的方法有6个:






matchTemplate介绍

  重点api为matchTemplate:

void cvMatchTemplate(const CvArr* image, const CvArr* templ, CvArr* result, int method)
image :原图像
temp1 :模板图像
result:保存匹配度的结果图像
method:方式选择(0-5,对应前面几种匹配度的计算方法)


代码实现

  这里是在android设备上用jni实现的,利用该模板匹配实现的,预览界面物体跟踪代码(注意:代码没有优化,非常卡,而且跟踪成功性不高,只能作为演示参考)

JNIEXPORT void Java_com_example_camera_1opencv_1android_PreviceGray_grayProc(JNIEnv* env, jclass obj, jlong imageGray,jint touch_x,jint touch_y){
int width,height;
int k = 0,n = 0,i,j;
CvScalar s;

int result_cols;
int result_rows;

Mat result;
Mat mat = Mat(*((Mat*)imageGray));
width = mat.rows;
height = mat.cols;

result_cols = height - Template + 1;
result_rows = width - Template + 1;

double minVal;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
int match_method = CV_TM_SQDIFF;

cv::Mat img = cv::Mat(Template,Template,CV_8UC3,cv::Scalar(0,0,0));
IplImage pI = mat;
IplImage pI_2 = img;

Mat img_display = cv::Mat(width,height,CV_8UC3,cv::Scalar(0,0,0));
IplImage pI_3 = img_display;
for(i=0;i<width;i++){
for(j=0;j<height;j++){
s = cvGet2D(&pI,i,j);
cvSet2D(&pI_3,i,j,s);
}
}

for(i=(touch_x-(Template/2));i<(touch_x+(Template/2));i++){
for(j=(touch_y-(Template/2));j<(touch_y+(Template/2));j++){
s = cvGet2D(&pI,j,i);
cvSet2D(&pI_2,k,n,s);
n++;
}
k++;
n=0;
}

result.create(result_cols, result_rows, CV_32FC1 );
/// Do the Matching and Normalize
matchTemplate( img_display, img, result, match_method);
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat() );
/// Localizing the best match with minMaxLoc

minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if(match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED ){
matchLoc = minLoc;
}else{
matchLoc = maxLoc;
}
rectangle(mat, matchLoc, Point(matchLoc.x + img.cols , matchLoc.y + img.rows ), Scalar::all(0), 2, 8, 0);
}

  上层传入了三个主要参数,分别表示预览的一帧画面,手指触屏点击的x,y轴坐标。
代码中首先将预览的图像复制了一份到img_display中,img_display作为原图像。
接着用手指点击的触屏坐标x,y为矩阵中心,Template为矩阵宽、高的矩形作为目标模板图像。
新建了和原图像大小的result图像作为保存匹配度的结果图像。

调用matchTemplate函数来取到匹配度保存到result图像中,minMaxLoc函数在result图像中,找到它的最大、最小值对应的像素点位置分别保存到minLoc、maxLoc中。
根据matchTemplate的匹配度计算方法不同,则result中匹配度最大值为最适合的匹配坐标,还是匹配度最小值为匹配坐标,从minLoc、maxLoc中选出最适合匹配坐标后,
存入到matchLoc中。

最后在预览图像上,matchLoc坐标位置画方框,表示皮匹配跟踪到了该模板图像。

参考代码如下:http://download.csdn.net/detail/u011630458/8405791
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: