求高手帮忙翻译一段基于OPENCV的运动目标检测的程序,详细翻译,老师会提问

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求高手帮忙翻译一段基于OPENCV的运动目标检测的程序,详细翻译,老师会提问相关的知识,希望对你有一定的参考价值。

#include "cv.h"
#include "highgui.h"
#include <time.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
const double MHI_DURATION = 0.1;
const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05;
const int N = 3;
const int CONTOUR_MAX_AERA = 10;
IplImage **buf = 0;
int last = 0;
IplImage *mhi = 0;
CvFilter filter = CV_GAUSSIAN_5x5;
CvConnectedComp *cur_comp, min_comp;
CvConnectedComp comp;
CvMemStorage *storage;
CvPoint pt[4];
void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )

double timestamp = clock()/1.;
CvSize size = cvSize(img->width,img->height);
int i, idx1, idx2;
IplImage* silh;
IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );
CvMemStorage *stor;
CvSeq *cont;
/*先进行数据的初始化*/
if( !mhi || mhi->width != size.width || mhi->height != size.height )

if( buf == 0 )

buf = (IplImage**)malloc(N*sizeof(buf[0]));
memset( buf, 0, N*sizeof(buf[0]));

for( i = 0; i < N; i++ )

cvReleaseImage( &buf[i] );
buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
cvZero( buf[i] );

cvReleaseImage( &mhi );
mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
cvZero( mhi );

cvCvtColor( img, buf[last], CV_BGR2GRAY );
idx1 = last;
idx2 = (last + 1) % N;
last = idx2;
silh = buf[idx2];
cvAbsDiff( buf[idx1], buf[idx2], silh );
cvThreshold( silh, silh, 30, 255, CV_THRESH_BINARY );
cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION );
cvCvtScale( mhi, dst, 255./MHI_DURATION,
(MHI_DURATION - timestamp)*255./MHI_DURATION );
cvCvtScale( mhi, dst, 255./MHI_DURATION, 0 );
cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 );
cvPyrDown( dst, pyr, 7 );
cvDilate( pyr, pyr, 0, 1 );
cvPyrUp( pyr, dst, 7 );
stor = cvCreateMemStorage(0);
cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor);
cvFindContours( dst, stor, &cont, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
for(;cont;cont = cont->h_next)

CvRect r = ((CvContour*)cont)->rect;
if(r.height * r.width > CONTOUR_MAX_AERA)

cvRectangle( img, cvPoint(r.x,r.y),
cvPoint(r.x + r.width, r.y + r.height),
CV_RGB(255,0,0), 1, CV_AA,0);


cvReleaseMemStorage(&stor);
cvReleaseImage( &pyr );


cvReleaseMemStorage(&stor);
cvReleaseImage( &pyr );

下面部分就不需要翻译了
剩下部分
int main( int argc, char** argv )

IplImage* motion = 0;
CvCapture* capture = 0;
capture = cvCaptureFromFile("D://Capture1.avi");
if( capture )
cvNamedWindow( "视频分析", 1 );

for(;;)

IplImage* image;
if( !cvGrabFrame( capture ))
break;
image = cvRetrieveFrame( capture );
if( image )

if( !motion )

motion = cvCreateImage( cvSize(image->width,image->height), 8, 1 );
cvZero( motion );
motion->origin = image->origin;


update_mhi( image, motion, 60);
cvShowImage( "视频分析", image );

if( cvWaitKey(10) >= 0 )
break;

cvReleaseCapture( &capture );
cvDestroyWindow( "视频分析" );

return 0;

这种运动目标检测的方法还是很经典的,下面写了一些注释仅作参考,希望对你有所帮助。

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <time.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
const double MHI_DURATION = 0.1;//定义运动跟踪的最大时间
const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05;
const int N = 3;//定义数组的维度为3
const int CONTOUR_MAX_AERA = 10;//定义的阈值
IplImage **buf = 0;
int last = 0;
IplImage *mhi = 0;
CvFilter filter = CV_GAUSSIAN_5x5;//高斯卷积滤波
CvConnectedComp *cur_comp, min_comp;//定义连通域操作的存储
CvConnectedComp comp;//定义连通域操作的存储
CvMemStorage *storage;//定义内存分配
CvPoint pt[4];//定义点的存储
/*****************************
*下面update_mhi函数输入img,输出识别结果dst,阈值diff_threshold
*/
void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )

double timestamp = clock()/1.; //返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元
CvSize size = cvSize(img->width,img->height); //获取图像的宽和高
int i, idx1, idx2;
IplImage* silh;
IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );//
CvMemStorage *stor;//申请内存
CvSeq *cont;//定义保存数据的结构
/*先进行数据的初始化*/
if( !mhi || mhi->width != size.width || mhi->height != size.height )

//分配内存操作:如果buf是空值,则分配存储空间
if( buf == 0 )

buf = (IplImage**)malloc(N*sizeof(buf[0]));//利用malloc动态分配内存
memset( buf, 0, N*sizeof(buf[0]));//作用是在一段内存块中填充某个给定的值,此处值为0

//创建通道为N=3,大小为size的图像存储
for( i = 0; i < N; i++ )

cvReleaseImage( &buf[i] );//释放buf
buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );//创建buf[i]
cvZero( buf[i] );//初始化为0

cvReleaseImage( &mhi );//释放变量mhi
mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );//创建mhi,大小为size,深度为IPL_DEPTH_32F,1个通道
cvZero( mhi ); ///初始化为0

cvCvtColor( img, buf[last], CV_BGR2GRAY );//将RGB图像img转换成gray灰度图像buf
idx1 = last;//将last赋值到idx1
idx2 = (last + 1) % N; //计算(last + 1)除以N的余数
last = idx2;//将idx2赋值到last
silh = buf[idx2];//将buf[idx2]赋值到silh
//下面计算buf[idx1]与buf[idx2]差的绝对值,输出结果存入silh
cvAbsDiff( buf[idx1], buf[idx2], silh );
//下面对单通道数组silh应用固定阈值操作,阈值为30,阈值化类型为CV_THRESH_BINARY最大值为255
cvThreshold( silh, silh, 30, 255, CV_THRESH_BINARY );
//去掉影像(silh) 以更新运动历史图像为mhi,当前时间为timestamp,运动跟踪的最大时间为MHI_DURATION=0.1
cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION );
//下面对mhi进行线性变换操作,输出结果存入dst:dst(I)=mhi(I)*第二个参数 + 第三个参数
cvCvtScale( mhi, dst, 255./MHI_DURATION,
(MHI_DURATION - timestamp)*255./MHI_DURATION );
cvCvtScale( mhi, dst, 255./MHI_DURATION, 0 );
cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 );//对dst进行中值滤波
cvPyrDown( dst, pyr, 7 );//利用卷积滤波器对dst进行下采样
cvDilate( pyr, pyr, 0, 1 );//对图像pyr使用3*3长方形进行膨胀操作
cvPyrUp( pyr, dst, 7 );//利用卷积滤波器对dst进行上采样
stor = cvCreateMemStorage(0);//动态内存存储创建内存块
cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor);//创建存储结构
//函数cvFindContours为寻找图像dst的角点,数据存入cont中,其中包含角点的坐标值
cvFindContours( dst, stor, &cont, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
for(;cont;cont = cont->h_next)

CvRect r = ((CvContour*)cont)->rect;//创建矩形区域
if(r.height * r.width > CONTOUR_MAX_AERA)

//下面是在图像Img上绘制红色的矩形框,利用左上点和右下点
cvRectangle( img, cvPoint(r.x,r.y),
cvPoint(r.x + r.width, r.y + r.height),
CV_RGB(255,0,0), 1, CV_AA,0);


cvReleaseMemStorage(&stor);//释放内存
cvReleaseImage( &pyr );//释放结构体


int _tmain(int argc, _TCHAR* argv[])

IplImage* motion = 0;
CvCapture* capture = 0;
capture = cvCaptureFromFile("D://Capture1.avi");//获取视频文件
if( capture )
cvNamedWindow( "视频分析", 1 );//创建窗口

for(;;)

IplImage* image;
if( !cvGrabFrame( capture ))//如果读取视频失败,则退出
break;
image = cvRetrieveFrame( capture );//获取图像
if( image )

if( !motion )

motion = cvCreateImage( cvSize(image->width,image->height), 8, 1 );
cvZero( motion );
motion->origin = image->origin;


update_mhi( image, motion, 60);//运动目标检测,阈值为60
cvShowImage( "视频分析", image );//在窗口中显示图像

if( cvWaitKey(10) >= 0 )
break;

cvReleaseCapture( &capture );//释放
cvDestroyWindow( "视频分析" );//释放窗口

return 0;
参考技术A 纳闷,opencv书上不是有各个函数的功能吗,也可以上网查啊,我不具体看了,大概看一下吧
如果你知道目标提取的一些方法,这个看懂不难,抱歉没啥时间给你看,自己努力下吧。
大致的思路是:通过背景差或帧差的方法获取两者的差别,并通过设定阈值,将差别较大的认为是前景目标,然后通过一些腐蚀、膨胀、滤波(比如中值滤波)提取出前景目标,然后去除小目标减少干扰,并用矩形框将结果框出来,很简单,自己对照着这个思想好好看看代码吧,凡是要靠自己努力才能成长。祝学业有成~
void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )

double timestamp = clock()/1.;
CvSize size = cvSize(img->width,img->height);
int i, idx1, idx2;
IplImage* silh;
IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );
CvMemStorage *stor;
CvSeq *cont;
/*先进行数据的初始化*/
if( !mhi || mhi->width != size.width || mhi->height != size.height )

if( buf == 0 )

buf = (IplImage**)malloc(N*sizeof(buf[0]));
memset( buf, 0, N*sizeof(buf[0]));

for( i = 0; i < N; i++ )

cvReleaseImage( &buf[i] );
buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
cvZero( buf[i] );

cvReleaseImage( &mhi );
mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
cvZero( mhi );

cvCvtColor( img, buf[last], CV_BGR2GRAY ); //前面没看,我想是将rgb图像转为灰度图像,可能create一下单通道的图像,存放转换结果的。
idx1 = last;
idx2 = (last + 1) % N;
last = idx2;
silh = buf[idx2];
cvAbsDiff( buf[idx1], buf[idx2], silh ); //做差,我想是通过差分的方法,提取前景目标的,也就是当前图像与背景图像作差,提取前景目标。
cvThreshold( silh, silh, 30, 255, CV_THRESH_BINARY );//这里阈值化,相差30像素以上为前景目标
cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION );
cvCvtScale( mhi, dst, 255./MHI_DURATION,
(MHI_DURATION - timestamp)*255./MHI_DURATION );
cvCvtScale( mhi, dst, 255./MHI_DURATION, 0 );
cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 );//滤波,平滑,去噪
cvPyrDown( dst, pyr, 7 );//降采样
cvDilate( pyr, pyr, 0, 1 ); //膨胀处理,让前景变得圆滑,以及一些小碎片连接起来
cvPyrUp( pyr, dst, 7 );
stor = cvCreateMemStorage(0);
cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor);//创序列
cvFindContours( dst, stor, &cont, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));//找轮廓及个数
for(;cont;cont = cont->h_next)

CvRect r = ((CvContour*)cont)->rect;//加上矩形框,也就是将前景目标框出来
if(r.height * r.width > CONTOUR_MAX_AERA)

cvRectangle( img, cvPoint(r.x,r.y),
cvPoint(r.x + r.width, r.y + r.height),
CV_RGB(255,0,0), 1, CV_AA,0);


cvReleaseMemStorage(&stor);
cvReleaseImage( &pyr );


cvReleaseMemStorage(&stor);
cvReleaseImage( &pyr );
参考技术B #包括“简历。”#包括“highgui。”#包括<高>时间。#包括<数学的。”#包括< ctype小时>。#包括<工作室的。“#包括<字符串>的。一双mhi_duration =0.1;一双max_time_delta =0.5;一双min_time_delta =0.05;整型常量=3;整型常量contour_max_aera =10;iplimage * * BCN =0;最后=0;iplimage *三菱重工=0;cvfilter cv_gaussian_5x5滤波器;cvconnectedcomp * cur_comp,min_comp;cvconnectedcomp补偿;cvmemstorage*;cvpoint铂[ 4];无效update_mhi(iplimage * - *,iplimage夏令时,国际diff_threshold)双时间戳= clock() / 1。;cvsize大小= cvsize(- - - - > >宽度,高度);在我,idx1,idx2;iplimage * silh;iplimage *芘= cvcreateimage(cvsize((size.width及- 2)/ 2,(size.height及- 2)/2),8,1);cvmemstorage *站;cvseq *续;先进行数据的初始化/ * * /如果(!三菱重工| |三菱重工- >宽度!= size.width | |三菱重工- >高度!= size.height)如果(缓冲区= =0)但是=(iplimage * *(*)内存大小(字节[ 0]));memset(缓冲区,0,* size of(字节[ 0]));为(=0;我的;我+ +)cvreleaseimage(&,[我]);但是[我] = cvcreateimage(大小,ipl_depth_8u,1);cvzero(字节[我]);cvreleaseimage(与三菱重工);三菱重工= cvcreateimage(大小,ipl_depth_32f,1);cvzero(三菱重工);cvcvtcolor(1mg,但是[上],cv_bgr2gray);最后idx1=;idx2=(上+1)%氮;最后idx2=;silh =但是[ idx2];cvabsdiff(缓冲区缓冲区idx2[ idx1],[ ],silh);cvthreshold(silh,silh,30,255,cv_thresh_binary);cvupdatemotionhistory(silh,三菱重工,时间戳,mhi_duration);cvcvtscale(三菱重工,测试,255/ mhi_duration,(mhi_duration -时间)* 255/ mhi_duration。);cvcvtscale(三菱重工,测试,255/ mhi_duration,0。);cvsmooth(夏令时间,日光节约时间,cv_median,3,0,0,0);cvpyrdown(夏令时,芘,7);cvdilate(吡啶酚,酚,0,1);cvpyrup(芘,测试,7);故事= cvcreatememstorage(0);续= cvcreateseq(cv_seq_eltype_point,size of(cvseq),大小(cvpoint),故事);cvfindcontours(夏令时,故事,和控制,尺寸(cvcontour),cv_retr_list,cv_chain_approx_simple,cvpoint(0 , 0));为(;控制;控制=续- > h_next)cvrect =((cvcontour *)续)- >矩形;如果(r.height * r.width > contour_max_aera)cvrectangle(1mg,cvpoint(支持,酵母),cvpoint(支持+ r.width,酵母+ r.height),cv_rgb(255,0,0),1,cv_aa,0);cvreleasememstorage(与故事);cvreleaseimage(与他们);cvreleasememstorage(与故事);cvreleaseimage(与他们);

诠释主体(国际argc,字符* * argv)iplimage *运动=0;cvcapture *捕捉=0;拍摄cvcapturefromfile(“:/ / capture1的。”);如果(捕获)cvnamedwindow(“视频分析”,1);为(;;)iplimage *图像;如果(!cvgrabframe(捕获))打破;图像cvretrieveframe(捕获);如果(图像)如果(!运动)运动= cvcreateimage(cvsize(图像- >宽度,图像- >高度),8,1);cvzero(运动);运动- >起源=图像- >起源;update_mhi(图像,运动,60);cvshowimage(“视频分析”,形象);如果(cvwaitkey(10)> =0)打破;cvreleasecapture(捕捉);cvdestroywindow(“视频分析”);返回0;

希望采纳
参考技术C 楼上说的很好,我白忙了半天。

运动目标检测——光流法与opencv代码实现

参考技术A

运动目标的检测的其主要目的是 获取目标对象的运动参数(位置、速度、加速度等)及运动轨迹 ,通过进一步分析处理,实现对目标行为更高层级上的理解。
运动目标检测技术目的是 从序列图像中将变化区域从背景图像中提取出来 ,常用于视频监视、图像压缩、三维重构、异常检测等。

运动目标检测主流方法有帧差法、背景差法、光流法等。光流法源于 仿生学 思想,更贴近于直觉,大量昆虫的视觉机理便是基于光流法。
二十世纪五十年代心理学家Gibson在他的著作“The Perception of Visual World”中首次提出了以心理学实验为基础的光流法基本概念,而直到八十年代才由Horn、Kanade、Lucash和Schunck创造性地将灰度与二维速度场相联系,引入光流约束方程的算法,对光流计算做了奠基性的工作。

光流(optical flow):由于目标对象或者摄像机的移动造成的图像对象在连续两帧图像中的移动。

小球在连续五帧运动构成的光流 小球在连续五帧运动构成的光流

通俗说,对于一个图片序列,把每张图像每个像素在连续帧之间的运动速度和方向( 某像素点在连续两帧上的位移矢量 )找出来就是光流场。

第t帧的时A点的位置是(x1, y1),第t+1帧时A点位置是(x2,y2),则像素点A的位移矢量:(ux, vy) = (x2, y2) - (x1,y1)

如何知道第t+1帧的时候A点的位置涉及到不同的光流计算方法,主要有四种:基于梯度的方法、基于匹配的方法、基于能量的方法、基于相位的方法。

光流法依赖于三个假设:

根据所形成的光流场中 二维矢量的疏密程度 ,光流法可分为稠密光流与稀疏光流。

基于区域匹配生成的稠密光流场 基于区域匹配生成的稠密光流场

稀疏光流只对有 明显特征的组点 (如角点)进行跟踪,计算开销小。

基于特征匹配发生成的稀疏光流场 基于特征匹配发生成的稀疏光流场

http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/video/doc/motion_analysis_and_object_tracking.html#calcopticalflowfarneback
(1)calcOpticalFlowPyrLK
基于金字塔LK光流算法,计算某些点集的稀疏光流。
参考论文《Pyramidal Implementation of the Lucas Kanade Feature TrackerDescription of the algorithm》
(2)calcOpticalFlowFarneback
基于Gunnar Farneback 的算法计算稠密光流。
参考论文《Two-Frame Motion Estimation Based on PolynomialExpansion》
(3)CalcOpticalFlowBM
通过块匹配的方法来计算光流
(4)CalcOpticalFlowHS
基于Horn-Schunck 的算法计算稠密光流。
参考论文《Determining Optical Flow》
(5)calcOpticalFlowSF
论文《SimpleFlow: A Non-iterative, Sublinear Optical FlowAlgo》的实现

LK光流法效果 LK光流法效果

以上是关于求高手帮忙翻译一段基于OPENCV的运动目标检测的程序,详细翻译,老师会提问的主要内容,如果未能解决你的问题,请参考以下文章

急!!!opencv做目标跟踪的时候,怎样把目标用矩形圈出来

运动目标检测——光流法与opencv代码实现

opencv运动车里检测跟踪轨迹不对

opencv 实现实时检测,求大神帮忙

运动对象检测和描述

求基于OpenCV的三帧差分算法代码