运动目标检测__光流法
以下内容摘自一篇硕士论文《视频序列中运动目标检测与跟踪算法的研究》:
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 );
int i;
int corner_count = 1000;
CvTermCriteria criteria;
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>
using namespace 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 = new CvPoint2D32f[ MAX_CORNERS];
CvPoint2D32f * move_new_point = new CvPoint2D32f[ MAX_CORNERS];
char *features_found = new char[MAX_CORNERS];
float *features_error = new float[MAX_CORNERS];
CvTermCriteria criteria;
criteria = cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 64, 0.01);
while(1)
{
int i,j;
int dx, dy;
int p = 0;
int rows, cols;
int countn = 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
相关文章:

读完这45篇论文,“没人比我更懂AI了”
作者 | 黄海广 转载自机器学习爱好者(ID:ai-start-com) 导读:AI领域的发展会是IT中最快的。我们所看到的那些黑科技,其后无不堆积了大量论文,而且都是最新、最前沿的论文。从某种角度来讲,它们所用的技术跟…

深入理解JVM——虚拟机GC
对象是否存活 Java的GC基于可达性分析算法(Python用引用计数法),通过可达性分析来判定对象是否存活。这个算法的基本思想是通过一系列"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当…

2019年最新华为、BAT、美团、头条、滴滴面试题目及答案汇总
作者 | 苏克1900来源 | 高级农民工(ID:Mocun6)【导语】最近 GitHub 上一个库火了,总结了 阿里、腾讯、百度、美团、头条等国内主流大厂的技术面试题目,目前 Star 2000,还在持续更新中,预计会火下…

华胜天成ivcs云系统初体验2
重启完成以后,就看到传统的linux init3级别的登录界面。输入用户名root 密码:123456 (默认)接下来的工作是配置一些东西,让它跑起来。首先,要修改IP地址,还有机器名。输入命令:ivcs…

OpenCV中响应鼠标信息cvSetMouseCallback函数的使用
转自:http://blog.csdn.net/haihong84/article/details/6599838 程序代碼如下: #include <cv.h> #include <highgui.h> #include <stdio.h void onMouse(int event,int x,int y,int flags,void* param ); int main(int argc, char** …

日常遇到的一些问题或知识的笔记(一)
1、坑爹的sessionStorage 一直以为sessionStorage、localStorage跟cookie一样,只要存在,整个域名下都可见,直到新开了一个窗口tab页,惊奇的发现下面的sessionStorage丢失了! Web Storage 包含如下两种机制:…

你是“10倍工程师”吗?这个事,国外小伙伴们都快“吵”起来了
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】近日,推特上一个话题“10x工程师”异常火爆,引发的热议经久不散。这个话题由一位印度初创公司投资人 Shekhar Kirani 的一条推特引发,他写道;“如果…

运动目标跟踪__kalman
转自:http://blog.csdn.net/lindazhou2005/article/details/1534234 1、 什么是卡尔曼滤波器(What is the Kalman Filter?) 在学习卡尔曼滤波器之前,首先看看为什么叫“卡尔曼”。跟其他著名的理论(例如傅立叶变换&a…

Spring工厂常识
环境搭建导入Sring对应的jar包导入Spring依赖的commons-loggin包导入log4j.properties在src下导入ApplicationContext.xml在任意目录下是一个轻量级的企业开发框架核心:IOC , AOP编程IOC:也就是inverse of control 控制反转 就是讲创建对象的权利转移到工厂中,从而实现解耦合和…

iframe子页面操作父页面
2019独角兽企业重金招聘Python工程师标准>>> 最近经常用到iframe,用的最多的就是在子页面中操作父页面的方法或变量等,总结了用到的几种方法,如下: var tableName window.parent.frames["mainFrame"].tNam…

ASP.NET MVC动作过滤器
ASP.NET MVC中包含以下4种不同类型的Action Filter: 类型使用时机接口实现方法授权过滤器(Authorization Filter)在执行任何Filter或Action之前被执行,用于进行身份验证IAuthorizationFilterAuthorizeAttribute动作过滤器(Action Filter)在执行Action之前…

什么限制了GNN的能力?首篇探究GNN普适性与局限性的论文出炉!
作者 | Andreas Loukas译者 | 凯隐责编 | Jane出品 | AI科技大本营(ID: rgznai100)【导读】GNN是目前机器学习领域的热门网络之一,肯多研究与技术分享相比不可知的深度学习网络模型,GNN 有哪些吸引我们的优势及硬核实力。然而&…

OpenCV运动检测跟踪(blob track)框架组成模块详解
在..\opencv\doc\vidsurv文件夹中有三个doc文件,Blob_Tracking_Modules、Blob_Tracking_Tests、TestSeq,其中Blob_Tracking_Modules必须需要详读的。 “FG/BG Detection” module performsforeground/background segmentation for each pixel. “Blob E…

vi和软件安装
一 vi编辑器简介 vim 全屏幕纯文本编辑器 二 vim使用 1 vi 模式 vi 文件名 命令模式 输入模式 末行模式 命令----》输入 a:追加 i:插入 o:打开 i 命令----》末行 :w 保存 :q 不保存退出 2 命令模式操作 1)…

鸟哥学习笔记---网络安全基础
yum clean [packages|header|all] packages:将已下载的软件文件删除 headers:将下载的软件文件头删除 all:将所有容器数据都删除 添加镜像站点:mirrorlisthttp://ftp.twaren.net/Linux/CentOS/6/os/x86_64/ http://free.nchc.org.tw/drbl-core/i386/RPMS…

使用纯C++实现SQL Server2005 数据库读写操作详细步骤
环境:虚拟机windows xp,vs2008 SQLServer 2005 Express 数据库访问技术采用ADO。 需要安装的软件包括:microsoft_dotnetfxchs2.0.exe、WindowsInstaller-KB893803-v2-x86.exe、SQLEXPR32_CHS.EXE、SQLServer2005_SSMSEE.msi、SQLServer200…

硬核吃瓜!上万条数据撕开微博热搜真相
作者 | 徐麟来源 | 转载自数据森麟(ID:shujusenlin)吃瓜前言关于新浪微博,向来都是各路吃瓜群众聚集之地,大家在微博中可以尽情吃瓜,各种类型的瓜应有尽有,只有你想不到的,没有你吃不到的。微博…

python类的__slots__属性、__del__属性、上下文(__enter__和__exit__)、
常规情况下,类的属性字典是共享的,而实例的字典是独立的。如果一个类的属性较少,但是拥有很多的实例,这些实例的属性字典会占用较多的内存空间。对这样的类来说,为了节省内存空间,可以使用__slots__类变量代…

普通帧,关键帧,空白关键帧的区别
1. 特点 帧——是进行flash动画制作的最基本的单位,每一个精彩的flash动画都是由很多个精心雕琢的帧构成的,在时间轴上的每一帧都可以包含需要显示的所有内容,包括图形、声音、各种素材和其他多种对象。 关键帧——顾名思义,有关键…

Spark入门系列(二)| 1小时学会RDD编程
作者 | 梁云1991转载自Python与算法之美(ID:Python_Ai_Road)导读:本文为 Spark入门系列的第二篇文章,主要介绍 RDD 编程,实操性较强,感兴趣的同学可以动手实现一下。RDD 是弹性分布式数据集(Resilient Dist…

Office2010启动慢的解决方法
以word2010为例: 解决启动慢的问题: 转自:http://www.blue1000.com/bkhtml/2011-12/70698.htm 首先启动Word2010,-->单击进入“文件”选项卡-->选择左边的“选项”按钮-->弹出“word选项”对话框窗口,-->…

如何在 Vue 项目中使用 echarts
数据的重要性我们大家都知道,就算再小的项目中都可能使用几个图表展示,我最近在做项目的过程中也是需要用到图表,最后选择了echarts 图表库,为什么选择 echarts,第一:简单上手容易,第二…

OpenCV实现在图像中写入汉字
由于OpenCV自带的cvInitFont和cvPutText函数不支持向图像中写入中文,参考http://www.opencv.org.cn/forum/viewtopic.php?t2083 中的方法,在windows7 64位机上用vs2008OpenCV2.3.1实现具体步骤如下: 1、新建一个控制台工程Test,先…

Operations Manager 2012 SP1配置部署系列之(二) SCOM监控SCVMM
你可以使用Operations Mangager连接到VMM上去监控VMM管理的虚拟机和虚拟机的主机的健康和可用性.你还可以监视VMM管理服务器的健康和可用性,VMM数据库服务器、存储库服务器,和矢量调制法的自服务门户web服务器.当你把VMM与Operations Mangager集成、VMM的…
ROS中base_link, odom, fixed_frame, target_frame和虚拟大地图map的关系
前面已经介绍了如何使用URDF建造机器人小车并显示在Rviz的仿真环境里面,但是小车是静止的。下面介绍如何让它在Rviz里面动起来,并理清URDF,TF 和 odom 的关系。 1. ROS中base_link, odom, fixed_frame, target_frame和虚拟大地图map的关系 一般在urdf文件…

谷歌新研究:基于数据共享的神经网络快速训练方法
作者 | Google Brain译者 | 凯隐责编 | 夕颜出品 | AI科技大本营(ID:rgznai100)导读:神经网络技术的普及离不开硬件技术的发展,GPU 和 TPU 等硬件型训练加速器带来的高算力极大的缩短了训练模型需要的时间,使得研究者们…

制作一个简单的linux
我这里是借助宿主机做的一个简单的Linux,我们只要知道一个Linux启动过程需要什么,这里制作就简单的多了。不过没有基础的也没关系,我写的很详细,没有基础的看了我写的步骤只要细心也是会做出来的,我这里的小Linux是很简…

nginx是什么,如何使用
一:nginx是什么? 二:nginx作为网关,需要具备什么?(nginx可以作为web服务器,但更多的时候,我们把它作为网关,因为它具备网关必备的功能:) 反向代理…

OpenCV中Mat数据结构使用举例
#include "stdafx.h"#include <string>#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;int _tmain(int argc, _TCHAR* argv[]){//创建一个用13j填充的 7 x 7 复矩阵-----1Mat M(7, 7, CV_32FC2, Scalar…

贾扬清加盟AI开发者大会!早鸟票抢购正式开启
整理 | 夕颜硬核 AI 技术大会,一年参加一次就够了。9 月 6日-7 日,2019 AI 开发者大会(AI ProCon)将在北京富力万丽酒店举行,人工领域技术领袖将再次齐聚一堂,探讨过去一年最新的 AI 技术趋势与变化&#x…