opencv求两张图像光流_光流(optical flow)和openCV中实现

转载请注明出处!

光流(optical flow)和openCV中实现

光流的概念:

是Gibson在1950年首先提出来的。

它是空间运动物体在观察成像平面上的像素运动的瞬时速度。是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的相应关系,从而计算出相邻帧之间物体的运动信息的一种方法。

一般而言。光流是因为场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

当人的眼睛观察运动物体时,物体的景象在人眼的视网膜上形成一系列连续变化的图像。这一系列连续变化的信息不断“流过”视网膜(即图像平面)。好像一种光的“流”,故称之为光流(optical flow)。光流表达了图像的变化,因为它包括了目标运动的信息。因此可被观察者用来确定目标的运动情况。

看以下的图。它展示了一个小球在5个连续的帧中的运动。箭头上的数字代表不同的帧。那个红色小球的运动构成了光流。

SouthEast

操作:

给你一个图上的一系列点,在另外一张图上找到与前面一些列点同样的点。

或者给你图I1上的点[ux, uy]T。找到I2上的点[ux

+ δx, uy + δy]T。最小化ε:

c7a09b2e1bae6e97af63b80492a4732a.png

上面增加Wx表示一块区域,一般跟踪一个区域的点。

在图形学应用中。在多张图上跟踪点(特征)是一项主要的操作:在一张图上找到一个对象,观察对象怎样移动。

基于特征点的跟踪算法大致能够分为两个步骤:

1)探測当前帧的特征点;

2)通过当前帧和下一帧灰度比較,预计当前帧特征点在下一帧的位置;

3)过滤位置不变的特征点,余下的点就是目标了。

特征点能够是Harris角点,也能够是边缘点等等。

考虑一个像素

65119217dee887bc9ebd66ab4b7dcfe6.png在第一帧的光强度(这里添加了一个维度时间。前面的时候我们仅仅是处理图像。所以没有必要时间。如今须要添加这个维度)。它移动了 

9efafd553106db015be1226d4097f254.png的距离到一下帧。用了

ae7eab6c0a929db7c65ae9787e9c9427.png时间。

由于像素点是一样的。光强度也没有发生变化(事实上这个光强度没有改变是非常多光流算法的基本如果)。。所以我们能够说:

39f64002d405ddb3c046b713fabfb33f.png

然后通过泰勒级数近似展开有:

77add3bcabffb17d13ac260ac7426f31.png

所以:

SouthEast

上面的等式叫做光流等式,偏导数能够求出来。但是 u和v是未知的,所以无法解决上的等式。但是有非常多方法能够解决问题,当中一个叫做Lucas-Kanade方法。

Lucas-Kanade:

有这么一个假定,全部的相邻像素有相似的行动,Lucas-Kanade方法使用3*3的一块区域,它假定这9个点有同样的行动,所以如今的问题变为有9个等式,2个未知量,这个问题当然可以解决。一个好的解决方案是使用最小二乘法。

令n=9,于是便有了9个等式:

1114004219080a4445a5b7e2966d2af0.png

SouthEast

d6ff4b5f7fd199720657c23e65b68680.png

SouthEast

当中q1,q2,…,代表像素点,

85c8d6d52497716d9d74ee90309ae08d.png是偏导,上面的等式能够写成以下的形式:A

v = b,当中:

SouthEast

然后,得到以下的:

f9eab3cccec73aa39da828382329bfc3.png

SouthEast

终于算出来的两个未知数的解是:

fabe655882884a9728ca45ff314a8b84.png

上面的解决小而连贯的运动。想想刚刚我们的如果是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

#include

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 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 status;

vector 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

{

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 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;

}

结果:任意取得一些特征点。特征点会随着车的移动而移动

2a4c0ff48d0e492e09e23eba869136c0.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

storm apache_Apache Storm的实时情绪分析示例

storm apache实时情感分析是指处理自然语言文本&#xff08;或语音&#xff09;流以提取主观信息。 琐碎的用例用于构建推荐引擎或查找社交媒体趋势。 我选择了Apache Storm作为实时处理引擎。 Storm非常强大&#xff08;我们正在生产中使用它&#xff09;&#xff0c;并且非常…

怎么用python画圆的公式_怎么用python画圆

python中内置了许多第三方库&#xff0c;来帮助它完成各种功能。Turtle库就是Python语言中一个很流行的绘制图像的函数库(推荐学习&#xff1a;Python视频教程)Turtl库用于绘制线、圆、其他形状或者文本这个库被介绍为一个最常用的用来给孩子们介绍编程知识的方法库&#xff0c…

嵌入式java基准测试_Java正则表达式库基准测试– 2015年

嵌入式java基准测试在尝试使Java在计算机语言基准游戏的regexdna挑战中排名第一时&#xff0c;我正在研究Java正则表达式库的性能。 我可以找到的最新网站是2010年的tusker.org 。因此&#xff0c;我决定使用Java Microbenchmarking Harness重做测试并发布结果&#xff08;破坏…

libgdx和unity_libgdx和Kotlin –类[2D平台原型]

libgdx和unity这篇文章是libgdx和Kotlin文章的后续文章。 我已经决定开发一个简单的2D平台程序的原型&#xff08;沿着我的早期文章中的Star Assault进行介绍&#xff09;&#xff0c;但是我一直在使用和学习Kotlin&#xff0c;而不是Java。 对于本教程&#xff0c;该项目应处…

java1.7开发环境_在Windows平台搭建Java 1.7开发环境

OS&#xff1a;Windows 7 or laterJava Version: 1.7.x本文具体的演示环境是&#xff1a;Windows 8.1&#xff0c;Java 1.7.0_45。一、安装JDK需要注意的是安装路径中不要出现非西文符号。实际上我一般喜欢在安装路径中也尽可能不出现空格。比如&#xff1a;在我的PC上&#xf…

gluon_带有Gluon Ignite和Dagger的JavaFX中的依赖注入

gluon依赖注入抽象框架Gluon Ignite在几个流行的依赖注入框架&#xff08;例如Spring&#xff0c;Dagger和Guice&#xff09;上创建了一个通用抽象。 目前&#xff0c;Gluon 页面仅包含一个示例&#xff0c;该示例使用Gluon Ignite和Google Guice作为依赖注入框架&#xff0c;…

couchbase_具有Couchbase,Java EE和WildFly的CRUD Java应用程序

couchbaseCouchbase是一个开源的NoSQL文档数据库。 它允许访问&#xff0c;索引和查询JSON文档&#xff0c;同时利用集成的分布式缓存来实现高性能数据访问。 开发人员可以使用不同的语言&#xff08;Java&#xff0c;Go&#xff0c;.NET&#xff0c;Node&#xff0c;PHP&…

java 对象的态_Java面向对象-------多态总结

1.多态&#xff1a;是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作&#xff0c;如图所示&#xff1a;多态性是对象多种表现形式的体现。2.多态作用&#xff1a;1. 消除类型之间的耦合关系2. 可替换性3. 可扩充性4…

netbeans连接数据库_NetBeans Java EE技巧#1 –数据库中的实体类

netbeans连接数据库NetBeans IDE是开发各种应用程序的绝佳选择。 具体来说&#xff0c;我每天都使用它来开发和维护Java EE应用程序。 在过去的几个发行版中&#xff0c;不仅Java EE的生产力提高了&#xff0c;而且NetBeans IDE还减少了开发应用程序的时间……使Java EE和NetBe…

jboss fuse 教程_使用JBoss Fuse和OpenShift进行Cloud Native Camel骑行

jboss fuse 教程红帽公司最近发布了一个微服务集成工具包&#xff0c;用于在OpenShift v3的Docker和Kubernetes环境中运行我们的微服务。 为了帮助人们更好地理解这一点&#xff0c;我将Rider Auto应用程序迁移到一组微服务中&#xff0c;该应用程序已经存在了一段时间&#xf…

javaone_JavaOne 2015 –又一年,又向前迈进了一步

javaoneJavaOne 2015 San Francisco于10月25日至29日举行。 我很自豪地说这是我第九个人参加JavaOne&#xff0c;第七个人是演讲者&#xff0c;第四个人是Oracle员工&#xff0c;第三个人是内容委员会成员&#xff0c;第二个人是项目负责人。 我认为对于JavaOne来说&#xff0c…

lnp和mysql分开安装_毕业设计之LNP+DISCUZ +分离的数据库操作

环境介绍&#xff1a;CentOS6.9最小化安装https://nginx.org/download/nginx-1.16.1.tar.gzhttps://www.php.net/distributions/php-7.3.14.tar.gzhttps://cdn.mysql.com//Downloads/MySQL-5.7/mysql-boost-5.7.29.tar.gznginxphp主机&#xff1a;192.168.111.141mysql主机&…

java中hotspot_Java 8中HotSpot选项的改进文档

java中hotspotOracle的HotSpot Java 8实现中引入的一些小但受欢迎的功能之一是在启动器的文档中添加了许多常见的HotSpot Java启动器 &#xff08; java &#xff09;选项/标志。 过去&#xff0c;甚至对某些相当常见的HotSpot JVM选项都感兴趣的开发人员不得不潜在地寻找多个不…

qchart折现图_Qt开发技术:QCharts(二)QCharts折线图介绍、Demo以及代码详解

若该文为原创文章&#xff0c;未经允许不得转载各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究敬请期待…红胖子&#xff0c;来也&#xff01;介绍了整体框架&#xff0c;开始动手码代码&#xff0c;按照顺…

各类算法思想

暴力枚举法 使用场景注意事项 1.建立一个简洁的搜索模型&#xff0c;变量尽可能少 2.尽可能减少搜索空间 递归与分治法 分治使用最广泛一类算法。采用递归的思想将较大规模的问题分成小问题来求。如果原问题可以分割成k个子问题&#xff0c;并且这些子问题可以重复利用&am…

eclipse neon_在自定义Java 9映像上运行Eclipse Neon

eclipse neon我已经开始修改自定义Java二进制运行时映像文件。 映像文件是打包为运行时平台的模块的配置。 基本上&#xff0c;默认映像包含组成Java运行时的所有内容。 自定义图像可以包含该图像的一些子集。 例如&#xff0c;我创建了一个仅包含“ compact 3”概要文件的映像…

java json注解_返回json用什么注解

返回json用“ResponseBody”注解&#xff0c;“ResponseBody”是作用在方法上的&#xff0c;“ResponseBody”表示该方法的返回结果直接写入“HTTP response body”中。本篇文章将介绍两种示例进行JSON返回注解方式演示。示例1ResponseBody是作用在方法上的&#xff0c;Respons…

java数据结构博客园_常见数据结构的Java实现

单链表的Java实现首先参考wiki上的单链表说明&#xff0c;单链表每个节点包含数据和指向链表中下一个节点的指针或引用。然后看代码import java.lang.*;public class SinglyLinkeList{Node start;public SinnglyLinkedList(){this.startnull;}public void addFront(Object newD…

jboss4 java_带有JBoss工具的OpenShift 3上的Java EE 7应用程序

jboss4 java您可以使用最新版本的JBoss Tools OpenShift插件在Eclipse中创建和管理OpenShift应用程序。 他们要么预先捆绑了最新的 JBoss Developer Studio&#xff08;9.0.0.GA&#xff09; &#xff0c;也可以将它们安装到现有的Eclipse Mars中。 这篇文章将引导您通过JBoss…

javaslang_使用Javaslang的Java 8中的功能数据结构

javaslangJava 8的lambda&#xff08;λ&#xff09;使我们能够创建出色的API。 它们极大地提高了语言的表达能力。 Javaslang利用lambda来基于功能模式创建各种新功能。 其中之一是功能性集合库&#xff0c;旨在替代Java的标准集合。 &#xff08;这只是鸟瞰图&#xff0c;您…