光流(optical flow)和openCV中实现
转载请注明出处!
!
!
http://blog.csdn.net/zhonghuan1992
光流(optical flow)和openCV中实现
光流的概念:
是Gibson在1950年首先提出来的。
它是空间运动物体在观察成像平面上的像素运动的瞬时速度。是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的相应关系,从而计算出相邻帧之间物体的运动信息的一种方法。
一般而言。光流是因为场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。
当人的眼睛观察运动物体时,物体的景象在人眼的视网膜上形成一系列连续变化的图像。这一系列连续变化的信息不断“流过”视网膜(即图像平面)。好像一种光的“流”,故称之为光流(optical flow)。光流表达了图像的变化,因为它包括了目标运动的信息。因此可被观察者用来确定目标的运动情况。
看以下的图。它展示了一个小球在5个连续的帧中的运动。箭头上的数字代表不同的帧。那个红色小球的运动构成了光流。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
操作:
给你一个图上的一系列点,在另外一张图上找到与前面一些列点同样的点。
或者给你图I1上的点[ux, uy]T。找到I2上的点[ux
+ δx, uy + δy]T。最小化ε:
上面增加Wx表示一块区域,一般跟踪一个区域的点。
在图形学应用中。在多张图上跟踪点(特征)是一项主要的操作:在一张图上找到一个对象,观察对象怎样移动。
基于特征点的跟踪算法大致能够分为两个步骤:
1)探測当前帧的特征点;
2)通过当前帧和下一帧灰度比較,预计当前帧特征点在下一帧的位置;
3)过滤位置不变的特征点,余下的点就是目标了。
特征点能够是Harris角点,也能够是边缘点等等。
考虑一个像素在第一帧的光强度(这里添加了一个维度时间。前面的时候我们仅仅是处理图像。所以没有必要时间。如今须要添加这个维度)。它移动了
的距离到一下帧。用了
时间。
由于像素点是一样的。光强度也没有发生变化(事实上这个光强度没有改变是非常多光流算法的基本如果)。。所以我们能够说:
然后通过泰勒级数近似展开有:
所以:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
上面的等式叫做光流等式,偏导数能够求出来。但是 u和v是未知的,所以无法解决上的等式。但是有非常多方法能够解决问题,当中一个叫做Lucas-Kanade方法。
Lucas-Kanade:
有这么一个假定,全部的相邻像素有相似的行动,Lucas-Kanade方法使用3*3的一块区域,它假定这9个点有同样的行动,所以如今的问题变为有9个等式,2个未知量,这个问题当然可以解决。一个好的解决方案是使用最小二乘法。
令n=9,于是便有了9个等式:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
当中q1,q2,…,代表像素点, 是偏导,上面的等式能够写成以下的形式:A
v = b,当中:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
然后,得到以下的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvbmdodWFuMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
终于算出来的两个未知数的解是:
上面的解决小而连贯的运动。想想刚刚我们的如果是9个像素点速度一致。由于现实中大而连贯的运动是普遍存在的,我们须要大的窗体来捕获运动。但是大窗体违背了运动连贯的如果。图像金字塔能够解决问题。(图像金字塔的内容以后本人掌握很多其它的再补充。如今不敢乱发表)。
OpenCV中的实现:
OpenCV提供了对上面介绍的方法的支持。函数名叫做:cv2.calcOpticalFlowPyrLK(),如今让我们在视频中跟踪一些点。
为了决定跟踪哪些点,使用cv2.goodFeaturesToTrack()。
我们得到第一帧。探測Shi-Tomasi角点,然后我们使用 Lucas-Kanade光流法来跟综这些点。
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp" #include <iostream>
#include <ctype.h> using namespace cv;
using namespace std; static void help()
{
// print a welcome message, and the OpenCV version
cout << "\nThis is ademo of Lukas-Kanade optical flow lkdemo(),\n"
"Using OpenCVversion "<< CV_VERSION << endl;
cout << "\nIt usescamera by default, but you can provide a path to video as an argument.\n";
cout << "\nHot keys:\n"
"\tESC - quitthe program\n"
"\tr -auto-initialize tracking\n"
"\tc - deleteall the points\n"
"\tn - switch the\"night\" mode on/off\n"
"To add/removea feature point click it\n" << endl;
} Point2f point;
bool addRemovePt = false; static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/)
{
if (event == CV_EVENT_LBUTTONDOWN)
{
point = Point2f((float)x, (float)y);
addRemovePt = true;
}
} int main(int argc, char** argv)
{
help(); VideoCapture cap;
TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03);
Size subPixWinSize(10, 10), winSize(31, 31); const int MAX_COUNT = 500;
bool needToInit = false;
bool nightMode = false; /*if (argc == 1 || (argc == 2 && strlen(argv[1])== 1 && isdigit(argv[1][0])))
cap.open(argc == 2 ? argv[1][0] - '0' :0);
else if (argc == 2)
cap.open(argv[1]);*/ cap.open("G:\\视频分析入门练习\\视频分析入门练习 - 附件\\sample.avi"); if (!cap.isOpened())
{
cout << "Could notinitialize capturing...\n";
return 0;
} namedWindow("LK", 1);
setMouseCallback("LK", onMouse, 0); Mat gray, prevGray, image;
vector<Point2f> points[2]; for (;;)
{
Mat frame;
cap >> frame;
if (frame.empty())
break; frame.copyTo(image);
cvtColor(image, gray, COLOR_BGR2GRAY); if (nightMode)
image = Scalar::all(0); if (needToInit)
{
// automaticinitialization
goodFeaturesToTrack(gray, points[1],100, 0.01, 10, Mat(), 3, 0, 0.04);
cornerSubPix(gray, points[1],subPixWinSize, Size(-1, -1), termcrit);
addRemovePt = false;
}
else if(!points[0].empty())
{
vector<uchar> status;
vector<float> err;
if (prevGray.empty())
gray.copyTo(prevGray);
calcOpticalFlowPyrLK(prevGray, gray,points[0], points[1], status, err, winSize,
3, termcrit, 0, 0.001);
size_t i, k;
for (i = k = 0; i <points[1].size(); i++)
{
if (addRemovePt)
{
if (norm(point -points[1][i]) <= 5)
{
addRemovePt = false;
continue;
}
} if (!status[i])
continue; points[1][k++] = points[1][i];
circle(image, points[1][i], 3, Scalar(0, 255, 0), -1, 8);
}
points[1].resize(k);
} if (addRemovePt&& points[1].size() < (size_t)MAX_COUNT)
{
vector<Point2f> tmp;
tmp.push_back(point);
cornerSubPix(gray, tmp, winSize,cvSize(-1, -1), termcrit);
points[1].push_back(tmp[0]);
addRemovePt = false;
} needToInit = false;
imshow("LK", image); char c = (char)waitKey(100);
if (c == 27)
break;
switch (c)
{
case 'r':
needToInit = true;
break;
case 'c':
points[0].clear();
points[1].clear();
break;
case 'n':
nightMode = !nightMode;
break;
} std::swap(points[1], points[0]);
cv::swap(prevGray, gray);
} return 0;
}
结果:任意取得一些特征点。特征点会随着车的移动而移动
光流(optical flow)和openCV中实现的更多相关文章
- 光流optical flow基本原理与实现
光流(optical flow)是什么呢?名字很专业,感觉很陌生,但本质上,我们是最熟悉不过的了.因为这种视觉现象我们每天都在经历.从本质上说,光流就是你在这个运动着的世界里感觉到的明显的视觉运动(呵 ...
- 光流法(optical flow)
光流分为稠密光流和稀疏光流 光流(optic flow)是什么呢?名字很专业,感觉很陌生,但本质上,我们是最熟悉不过的了.因为这种视觉现象我们每天都在经历.从本质上说,光流就是你在这个运动着的世界里感 ...
- [OpenCV-Python] OpenCV 中视频分析 部分 VI
部分 VI视频分析 OpenCV-Python 中文教程(搬运)目录 39 Meanshift 和 和 Camshift 目标 • 本节我们要学习使用 Meanshift 和 Camshift 算法在 ...
- opencv中的各种滤波设计
这篇文章写得太好了 ,感觉自己实在没有办法去补充这方面的知识点 我打算把高斯滤波和双边滤波还好好补充下 这篇文章转载自一个美丽的才女:小魏 连接地址:http://blog.csdn.net/xia ...
- 光流算法:关于OpenCV读写middlebury网站给定的光流的代码
Middlebury是每个研究光流算法的人不可能不使用的网站,Middlebury提供了许多标准的测试库,这极大地推进了光流算法的进展.Middlebury提供的标准库,其计算出的光流保存在后缀名为. ...
- 论文笔记之:Optical Flow Estimation using a Spatial Pyramid Network
Optical Flow Estimation using a Spatial Pyramid Network spynet 本文将经典的 spatial-pyramid formulation ...
- FlowNet: Learning Optical Flow with Convolutional Networks
作者:嫩芽33出处:http://www.cnblogs.com/nenya33/p/7122701.html 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者同意,必须保留此段声明:必须 ...
- OpenCV中OpenCL模块函数
It currently develop and test on GPU devices only. This includes both discrete GPUs(NVidia,AMD), as ...
- OpenCV中的KNN
一.K近邻 有两个类,红色.蓝色.我将红色点标记为0,蓝色点标记为1.还要创建25个训练数据,把它们分别标记为0或者1.Numpy中随机数产生器可以帮助我们完成这个任务 import cv2 impo ...
随机推荐
- Oracle排错总结
一.Oracle常规恢复之不安全恢复 http://www.cnblogs.com/jyzhao/p/4723994.html#2.11
- 图论trainning-part-1 F. Highways
F. Highways Time Limit: 1000ms Memory Limit: 10000KB 64-bit integer IO format: %lld Java class ...
- NYOJ 118 修路方案
修路方案 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修 ...
- 【U+B+D】三层框架 原理+实例
导读:三层的学习,也终于得到收获了.这个过程很艰辛,不止一次的想放弃.在这一个学习过程中,真的很感谢师傅的尽心.耐心.费心.其实真的很脆弱,现在回想起来都很不可思议. 一.基本概况 1,什么是三层 我 ...
- 九度oj 题目1450:产生冠军
题目描述: 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则如下: 如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C. 如果A打败了B ...
- 原 .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
大家都说反射耗性能,但是到底有多耗性能,哪些反射方法更耗性能:这些问题却没有统一的描述. 本文将用数据说明反射各个方法和替代方法的性能差异,并提供一些反射代码的编写建议.为了解决反射的性能问题,你可以 ...
- BZOJ 1829 [Usaco2010 Mar]starc星际争霸 ——半平面交
发现最终的结果只和$s1$,$s2$,$s3$之间的比例有关. 所以直接令$s3=1$ 然后就变成了两个变量,然后求一次半平面交. 对于每一个询问所属的直线,看看半平面在它的那一侧,或者相交就可以判断 ...
- BZOJ 4004 [JLOI2015]装备购买 ——线性基
[题目分析] 题目很简单,就是要维护一个实数域上的线性基. 仿照异或空间的线性基的方法,排序之后每次加入一个数即可. 卡精度,开long double 和 1e-6就轻松水过了. [代码] #incl ...
- 为什么上传文件的表单里要加个属性enctype----摘录
上传文件的表单中<form>要加属性enctype="multipart/form-data",很多人只是死记硬背知道上传表单要这么写,知其然而不知其所以然.那到底为什 ...
- 棋盘制作 BZOJ 1057
棋盘制作 [问题描述] 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴 ...