原文:

http://blog.csdn.net/fengbingchun/article/details/7721631

以下内容摘自一篇硕士论文《视频序列中运动目标检测与跟踪算法的研究》:

1950年Gibson首先提出了光流的概念,光流(optical flow)法是空间运动物体在观测成像面上的像素运动的瞬时速度。物体在运动的时候,它在图像上对应点的亮度模式也在做相应的运动,这种图像亮度模式的表观运动就是光流。光流的研究就是利用图像序列中像素的强度数据的时域变化和相关性来确定各自像素位置的“运动”。光流表达了图像的变化,因此可被观察者用来确定目标的运动情况。一般情况下,光流由相机运动、场景中目标运动或两者的共同运动产生。

光流场是由光流引申出来的,它指的是景物中可见像素点的三维速度矢量在成像表面投影形成的二维瞬时速度场。空间中的运动场转移到图像上就表示为光流场,光流场反映了图像上每一点的灰度变化趋势。光流场包含了被观察物体的运动信息以及有关景物丰富的三维结构的信息,它是如今计算机视觉及有关研究领域中的一个重要组成部分。

光流法检测运动目标,其基本思想是赋予图像中的每一个像素点一个速度矢量,从而形成了该图像的运动场。图像上的点和三维物体上的点在某一特定的运动时刻是一一对应的,根据各像素点的速度矢量特征对图像进行动态的分析。若图像中不存在运动目标,那么光流矢量在整个图像区域则是连续变化的,而当物体和图像背景中存在相对运动时,运动物体所形成的速度矢量则必然不同于邻域背景的速度矢量,从而将运动物体的位置检测出来。

光流不能由运动图像的局部信息来唯一的确定,例如,亮度等值线上的点或者亮度比较均匀的区域都无法唯一的确定其点的运动对应性,但是运动是可以进行观察得到。由此说明运动场和光流不一定是唯一对应的,即光流不一定是由物体运动产生的,反之如果物体发生了运动也不一定就能产生光流。但是一般情况下,表观运动和物体真实运动之间的差异是可以忽略的,可以用光流场代替运动场来分析图像中的运动目标及其相关的运动参数。

可以证明动能场不仅仅是分块连续的,并且其间断点恰好为物体的边缘。如此,我们便可以利用图像每一帧的运动场,在动能变化矩阵中提取极值点,便可以得到运动物体的边缘。可将动能大致相同的点归于同一物体,进而对图像序列进行分割,从而检测出多个运动目标。这样,我们就将运动目标检测问题,借助光流场转换为静态图像的区域分割问题。

算法步骤如下:

(1)令i=1,获得第i帧图像I(x,i);

(2)获得第i+1帧图像I(x,i+1);

(3)对图像去噪,得到去燥后图像I '(x, i)和I '(x, i+1);

(4)利用I '(x, i)和I '(x, i+1)计算得到光流场;

(5)计算得到局部动能场K(i);

(6)利用边缘检测算法(如基于小波的方法)局部动能场并分割图像得到不同的运动单元也理解为一个运动单元);

(7)由于目标一般较背景小,故提取出体积较运动单元作为检测目标;

(8)计算其质心作为目标位置;

(9)置i=i+1,重复(2)~(8),直至检测结束。

基于光流场分析的运动目标检测方法,不仅包含了被观察物体的运动信息,而且携带了三维结构的丰富信息,因此它不仅可以用于运动目标检测,还可以直接应用于运动目标跟踪,能够很精确的计算出运动目标的速度,同时在摄像机存在运动的情况下也能够检测出运动目标。而在实际的应用中,由于存在多光源、遮挡性、噪声和透明性等多方面的原因,光流场基本方程中的灰度守恒这个假设条件是得不到满足的,因此不能求解出正确的光流场,同时由于其采用的是迭代的求解计算方法,故需要的计算时间比较长,从而无法满足实时的要求,并且该方法受噪声的影响较大,因而该方法多适用于目标运动速度不大,图像噪声比较小的情况。

转自:http://blog.csdn.net/zht9961020/article/details/7032059

cvCalcOpticalFlowPyrLK函数在使用时,首先要确定特征点,也就是目标旧的位置。

本程序通过使用cvGoodFeaturesToTrack函数选择角点作为特征点。

本程序只是一个简单的运动检测,在具体应用过程中,可以根据自己的需要修正

#include<cv.h>

#include<highgui.h>

int main (int argc,char **argv)

{

CvCapture*capture = 0;

capture =cvCaptureFromCAM(  CV_CAP_ANY );

inti;

intcorner_count = 1000;

CvTermCriteriacriteria;

criteria =cvTermCriteria (CV_TERMCRIT_ITER |CV_TERMCRIT_EPS, 64, 0.01);

IplImage *src_img1;

IplImage *src_img2;

IplImage *dst_img;

IplImage *pre_img;

IplImage *eig_img;

IplImage *temp_img;

IplImage *prev_pyramid;

IplImage *curr_pyramid;

CvPoint2D32f *corners1;

CvPoint2D32f *corners2;

corners1 = (CvPoint2D32f *)cvAlloc (corner_count *sizeof (CvPoint2D32f));

corners2 = (CvPoint2D32f *)cvAlloc (corner_count *sizeof (CvPoint2D32f));

cvNamedWindow ("Image", 1);

char *status;

status = (char *)cvAlloc (corner_count);

while (1)

{

pre_img = cvQueryFrame(capture);

CvSize img_sz = cvGetSize(pre_img);

src_img1 = cvCreateImage(img_sz,IPL_DEPTH_8U, 1);

cvCvtColor(pre_img, src_img1, CV_RGB2GRAY);

dst_img = cvQueryFrame(capture);

src_img2 = cvCreateImage(img_sz,IPL_DEPTH_8U, 1);

cvCvtColor(dst_img, src_img2, CV_RGB2GRAY);

eig_img = cvCreateImage (img_sz,IPL_DEPTH_32F, 1);

temp_img = cvCreateImage (img_sz,IPL_DEPTH_32F, 1);

prev_pyramid = cvCreateImage (cvSize (src_img1->width + 8,src_img1->height / 3),IPL_DEPTH_8U, 1);

curr_pyramid = cvCreateImage (cvSize (src_img1->width + 8,src_img1->height / 3),IPL_DEPTH_8U, 1);

cvGoodFeaturesToTrack (src_img1, eig_img, temp_img, corners1, &corner_count, 0.001, 5, NULL);

cvCalcOpticalFlowPyrLK (src_img1, src_img2, prev_pyramid, curr_pyramid,

corners1, corners2, corner_count, cvSize (10, 10), 4, status, NULL, criteria, 0);

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

{

if (status[i])

cvLine (dst_img, cvPointFrom32f (corners1[i]),cvPointFrom32f (corners2[i]),CV_RGB (255, 0, 0), 1, CV_AA, 0);

}

cvShowImage ("Image", dst_img);

cvWaitKey (1);

cvReleaseImage (&src_img1);

cvReleaseImage (&src_img2);

cvReleaseImage (&eig_img);

cvReleaseImage (&temp_img);

cvReleaseImage (&prev_pyramid);

cvReleaseImage (&curr_pyramid);

}

cvDestroyWindow ("Image");

cvReleaseImage (&dst_img);

cvReleaseImage(&pre_img);

return 0;

}

转自:http://blog.csdn.net/zht9961020/article/details/7032061

cvCalcOpticalFlowPyrLK需要确定特征点。

本程序,通过帧差获得运动的点作为特征点。

本程序原本的目的是计算运动点的速度,通过修正可以进行运动跟踪。

#include<cv.h>

#include<highgui.h>

#include<iostream>

usingnamespace std;

int const MAX_CORNERS = 1000;

int main (int argc,char **argv)

{

CvCapture*capture = 0;

capture =cvCaptureFromCAM(  CV_CAP_ANY );  //get frame

IplImage *src_img1; //the previous frame (gray)

IplImage *src_img2; //the current frame(gray)

IplImge *dst_img;  //the result

IplImage *cur_img;

IplImage *pre_img;

CvPoint2D32f *move_old_point = newCvPoint2D32f[ MAX_CORNERS];

CvPoint2D32f *move_new_point = newCvPoint2D32f[ MAX_CORNERS];

char *features_found =new char[MAX_CORNERS];

float *features_error =new float[MAX_CORNERS];

CvTermCriteriacriteria;

criteria =cvTermCriteria (CV_TERMCRIT_ITER |CV_TERMCRIT_EPS, 64, 0.01);

while(1)

{

inti,j;

intdx, dy;

intp = 0;

introws, cols;

intcountn = MAX_CORNERS;

pre_img = cvQueryFrame(capture);

CvSize img_sz = cvGetSize(pre_img);

src_img1 = cvCreateImage(img_sz,IPL_DEPTH_8U, 1);

cvCvtColor(pre_img, src_img1, CV_RGB2GRAY);

cur_img = cvQueryFrame(capture);

src_img2 = cvCreateImage(img_sz,IPL_DEPTH_8U, 1);

cvCvtColor(cur_img, src_img2, CV_RGB2GRAY);

dst_img = (IplImage *)cvClone(cur_img);

IplImage *move_img = cvCreateImage(img_sz, IPL_DEPTH_8U, 1);

cvZero(move_img);

//cvAbsDiff(src_img1, src_img2,move_img);

cols = src_img1->width;

rows = src_img1->height;

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

{

for (j = 0; j<rows; j++)

{

double a = abs(cvGet2D(src_img1,j, i).val[0]-cvGet2D(src_img2,j, i).val[0]);

CvScalar b = cvScalar(a, 0, 0,0);

cvSet2D(move_img, j, i,b);

if (a>40)

{

if (p<MAX_CORNERS-1)

{

int d = ++p;

move_old_point[d].x =i;

move_old_point[d].y =j;

}

}

}

}

cvNamedWindow("moving object", 1);

cvShowImage("moving object", move_img);

CvSize Pyrsize = cvSize(src_img1->width +8,src_img1->height/3);

IplImage * pyrA = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1); //pyrA是需要寻找的点,不是没有初始化的

IplImage * pyrB = cvCreateImage(Pyrsize, IPL_DEPTH_32F, 1);

cvCalcOpticalFlowPyrLK(src_img1,

src_img2,

pyrA,

pyrB,

move_old_point,

move_new_point,

countn,

cvSize(10, 10),

3,

features_found,

features_error,

criteria,

0

);

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

{

int x1 = (int)move_new_point[i].x;

int x2 = (int)move_old_point[i].x;

int y1 = (int)move_new_point[i].y;

int y2 = (int)move_old_point[i].y;

dx =(int) abs(x1 -x2) ;

dy = (int)abs(y1 -y2);

if (dx >= 5&& dy >= 5)

{

cvLine (dst_img, cvPoint(x2, y2),cvPoint(x2+5,y2+5) , CV_RGB (255, 0, 0), 1,CV_AA, 0);

}

}

cvNamedWindow ("ImagePyrLK", 1);

cvShowImage ("ImagePyrLK", dst_img);

cvWaitKey (1);

cvReleaseImage (&dst_img);

cvReleaseImage(&pyrA);

cvReleaseImage(&pyrB);

cvReleaseImage(&move_img);

}

cvDestroyWindow("moving object");

cvDestroyWindow ("ImagePyrLK");

cvReleaseImage (&src_img1);

cvReleaseImage (&src_img2);

cvReleaseImage (&pre_img);

cvReleaseImage (&cur_img);

return 0;

}

其它参考文献:

1、  http://blog.csdn.net/gnuhpc/article/details/4355137

2、  http://blog.csdn.net/yang_xian521/article/details/6987447

3、  http://blog.csdn.net/gnuhpc/article/details/4355137

4、  http://blog.csdn.net/gnuhpc/article/details/4329857

5、  http://blog.csdn.net/gnuhpc/article/details/4291460

前景检测算法(十七)--基于光流算法相关推荐

  1. 【DA算法】基于DA算法的FIR滤波器的FPGA实现

    1.软件版本 quartusii 2.本算法理论知识 DA算法的主要特点是,巧妙地利用查找表将固定系数的MAC运算转化为查表操作,其运算速度不随系数和输入数据位数的增加而降低,而且相对直接实现乘法器而 ...

  2. 背包问题 贪心算法 java_JS基于贪心算法解决背包问题

    前面我们分享了关于js使用贪心算法解决找零问题,本文我们接着为大家介绍JS基于贪心算法解决背包问题. 贪心算法:在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做 ...

  3. burg算法 matlab,基于burg算法的谱估计研究及其matlab实现.doc

    基于burg算法的谱估计研究及其matlab实现 XX大学学院 毕业设计(论文) 相关资料 题目: 基于 其MATLAB实现 机电 系 电子信息工程 专业学 号: 学生姓名: 指导教师: (职称:讲 ...

  4. 【有限马尔科夫链状态分解+Kosaraju 算法】基于Kosaraju 算法和可达矩阵的有限马尔科夫链状态分解

    有限马尔科夫链状态分解+Kosaraju 算法 1 实验内容 2 理论基础 3 题目分析 4 按常返性和互通性对状态空间进行分解算法流程 4.1 强连通性和强连通分量 4.2 基于有向图 Kosara ...

  5. 路径规划算法:基于樽海鞘算法的路径规划算法- 附代码

    路径规划算法:基于樽海鞘优化的路径规划算法- 附代码 文章目录 路径规划算法:基于樽海鞘优化的路径规划算法- 附代码 1.算法原理 1.1 环境设定 1.2 约束条件 1.3 适应度函数 2.算法结果 ...

  6. 路径规划算法:基于蜻蜓算法的路径规划算法- 附代码

    路径规划算法:基于蜻蜓优化的路径规划算法- 附代码 文章目录 路径规划算法:基于蜻蜓优化的路径规划算法- 附代码 1.算法原理 1.1 环境设定 1.2 约束条件 1.3 适应度函数 2.算法结果 3 ...

  7. snm算法_基于SNM算法的大数据量中文商品清洗方法

    基于 SNM 算法的大数据量中文商品清洗方法 ∗ 张苗苗 苏 勇 [摘 要] 摘 要 SNM 算法即邻近排序算法,是英文数据清洗最常用的算法[ 1 ] . 目前为止,因为中英文语义的差异等一些原因,中 ...

  8. snm算法_基于SNM算法的大数据量中文地址清洗方法-计算机工程与应用.PDF

    基于SNM算法的大数据量中文地址清洗方法-计算机工程与应用 108 2014 ,50(5 ) Computer Engineering and Applications 计算机工程与应用 基于SNM ...

  9. 【智能优化算法】基于免疫算法求解单目标优化问题附matlab代码

    1 简介 自Farmer在1986年提出免疫机理可以在机器学习等工程问题中得到应用之后,相关人员就一直在探索免疫机理在工程实际中的应用技术.而De Castro等完善了算法结构和算法模型后,更为人工免 ...

最新文章

  1. RESTful之视图集ViewSet
  2. 安装batocera-linux教程_利用Grub2Win安装Batocera+Windows7双系统甚至多系统实战教程
  3. docker 查看日志_8个优秀Docker容器监控工具,收藏了
  4. txt文件可存储最大值_Verilog边码边学:十六进制文件读取$readmemh
  5. redis中value大小_查看redis的Value值大小
  6. 开课吧python小课学了有用吗-这个神仙技能,让你为所欲为!速来 !
  7. sklearn特征选择类库使用小结
  8. android开发之嵌入广告
  9. Java毕业设计——员工管理系统
  10. SPSS如何计算Cronbach alpha和进行折半信度检验
  11. Python双人五子棋
  12. 服务器显示共享文件夹的图标,Win7共享文件夹上的小锁图标怎么关闭?
  13. 天梯赛 L2-001 紧急救援 (25 分)
  14. 【js】仿照网易云音乐制作的音乐播放组件
  15. web项目开发一般流程
  16. easyExcell
  17. 博客文章导航(嵌入式宝藏站)(2023.2.20更新)
  18. 学Java可以做什么?这九大领域任你选!
  19. html input跳转页面,html input type=button 页面跳转
  20. 过年回家啦用python写一个宝石消消乐的游戏哄小朋友

热门文章

  1. repo一个新工程使用步骤
  2. Clojure 学习入门(16)- 正则表达式
  3. 從零開始學 ReactJS:最完整的 React 生態系入門教程
  4. android电池(五):电池 充电IC(PM2301)驱动分析篇
  5. UE4之vs2019IntelliSense错误
  6. android之下载文件
  7. windows之bat之批处理复制文件
  8. go语言学习之helloword
  9. 视频编解码(十一):编解码、显示调试常用命令总结
  10. Educoder Basemap和seaborn 第三关:Basemap