python光流法算法学习
基于python-opencv程序对光流法的理解
- 光流法的定义
- Lucas-Kanade光流原理
- Shi-Tomasi角点检测
- python-opencv代码demo
光流法的定义
光流法是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。
简单来说,光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”。光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。
光流法的前提假设:(1)相邻帧之间的颜色恒定,对于灰度图来说,亮度恒定;(2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比较“微小”;(3)保持空间一致性;即,同一子图像的像素点具有相同的运动
上面的三个假设对光流法的原理公式推导很重要,具体的推导公式不在具体阐述。同时也是判断使用光流法的使用条件,光流法主要分为两种,计算部分像素运动的:稀疏光流,以Lucas-Kanade为代表,计算所有像素运动的:稠密光流。下面将结合代码具体理解。
Lucas-Kanade光流原理
L-K算法基于上面三个假设。
(1)亮度恒定,就是同一点随着时间的变化,其亮度不会发生改变。这是基本光流法的假定(所有光流法变种都必须满足),用于得到光流法基本方程;
(2)小运动,这个也必须满足,就是时间的变化不会引起位置的剧烈变化,这样灰度才能对位置求偏导(换句话说,小运动情况下我们才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数),这也是光流法不可或缺的假定;
(3)空间一致,一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。这是Lucas-Kanade光流法特有的假定,因为光流法基本方程约束只有一个,而要求x,y方向的速度,有两个未知变量。我们假定特征点邻域内做相似运动,就可以连立区域内个个像素点的多个方程求取x,y方向的速度。
这样假设的具体原因可参考:https://blog.csdn.net/zyazky/article/details/52175069
L-K光流法是稀疏光流法,需要找到视频每帧的特征点,这个常用的有Shi-Tomasi角点和SIFT特征点。
Shi-Tomasi角点检测
opencv中调用goodFeaturesToTrack函数来实现角点检测
void goodFeaturesToTrack( InputArray image, OutputArray corners,int maxCorners, double qualityLevel, double minDistance,InputArray mask=noArray(), int blockSize=3,bool useHarrisDetector=false, double k=0.04 );
第一个参数image:8位或32位单通道灰度图像;
第二个参数corners:位置点向量,保存的是检测到的角点的坐标;
第三个参数maxCorners:定义可以检测到的角点的数量的最大值;
第四个参数qualityLevel:检测到的角点的质量等级,角点特征值小于qualityLevel*最大特征值的点将被舍弃;
第五个参数minDistance:两个角点间最小间距,以像素为单位;
第六个参数mask:指定检测区域,若检测整幅图像,mask置为空Mat();
第七个参数blockSize:计算协方差矩阵时窗口大小;默认为3
第八个参数useHarrisDetector:是否使用Harris角点检测,为false,则使用Shi-Tomasi算子;
第九个参数k:留给Harris角点检测算子用的中间参数,一般取经验值0.04~0.06。第八个参数为false时,该参数不起作用;
mask可以指定角点产生的区域,划定检测范围
python-opencv代码demo
opencv中提供了一个函数来实现K-L算法:cv2.calcOpticalFlowPyrLK()
nextPts,status,err = cv.calcOpticalFlowPyrLK( prevImg, nextImg, prevPts, nextPts[, status[, err[, winSize[, maxLevel[, criteria[, flags[, minEigThreshold]]]]]]])
返回值:
nextPtrs:输出一个二维点的向量,这个向量可以是用来作为光流算法的输入特征点,也是光流算法在当前帧找到特征点的新位置(浮点数)
status 标志:在当前帧当中发现的特征点标志status==1,否则为0
err :向量中的每个特征对应的错误率
输入值:
prevImg :上一帧图片
nextImg :当前帧图片
prevPts :上一帧找到的特征点向量
nextPts :与返回值中的nextPtrs相同
status :与返回的status相同
err :与返回的err相同
winSize :在计算局部连续运动的窗口尺寸(在图像金字塔中)
maxLevel: 图像金字塔层数,0表示不使用金字塔
criteria :寻找光流迭代终止的条件
flags :有两个宏,表示两种计算方法,分别是OPTFLOW_USE_INITIAL_FLOW:表示使用估计值作为寻找到的初始光流,OPTFLOW_LK_GET_MIN_EIGENVALS表示:使用最小特征值作为误差测量
minEigThreshold :该算法计算光流方程的2×2规范化矩阵的最小特征值,除以窗口中的像素数; 如果此值小于minEigThreshold,则会过滤掉相应的功能并且不会处理该光流,因此它允许删除坏点并获得性能提升。
下面附上代码:
读取视频第一帧,检测角点,然后使用K-L算法来迭代跟踪每个角点在每一帧的位置信息,最后画出运动轨迹。在做煤矿安全生产的项目时,考虑过使用光流法来检测传送到运动方向和速度,但是视频灰度图像中,运煤的传送带的灰度图亮度差异太小,导致角点产生了跳变。
import numpy as np
import cv2
import matplotlib.pyplot as pltcap = cv2.VideoCapture('1/12311sc.mp4')
# params for ShiTomasi corner detection 特征点检测
feature_params = dict( maxCorners = 10,qualityLevel = 0.1,minDistance = 10,blockSize = 3 )# Parameters for lucas kanade optical flow光流法参数
lk_params = dict(winSize = (15,15),maxLevel = 0,criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# Create some random colors 画轨迹
color = np.random.randint(0,255,(100,3))# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
roi = np.zeros_like(old_gray)
x,y,w,h = 266,143,150,150
roi[y:y+h, x:x+w] = 255
p0 = cv2.goodFeaturesToTrack(old_gray, mask = roi, **feature_params)# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)while(1):ret,frame = cap.read()if not ret:breakframe_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# calculate optical flowp1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)# Select good pointsgood_new = p1[st==1]good_old = p0[st==1]# draw the tracksfor i,(new,old) in enumerate(zip(good_new,good_old)):a,b = new.ravel()c,d = old.ravel()mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)frame = cv2.circle(frame,(a,b),3,color[i].tolist(),-1)img = cv2.add(frame,mask)cv2.imshow('frame',img)key = cv2.waitKey(60) & 0xffif key == 27: # 按下ESC时,退出breakelif key == ord(' '): # 按下空格键时,暂停cv2.waitKey(0)# Now update the previous frame and previous pointsold_gray = frame_gray.copy()p0 = good_new.reshape(-1,1,2)cv2.destroyAllWindows()
cap.release()
如有疑问或错误,欢迎大家指正交流。
python光流法算法学习相关推荐
- 稀疏光流python_python光流法算法学习
基于python-opencv程序对光流法的理解 光流法的定义 Lucas-Kanade光流原理 Shi-Tomasi角点检测 python-opencv代码demo 光流法的定义 光流法是空间运动物 ...
- python leetcode_leetcode 介绍和 python 数据结构与算法学习资料
for (刚入门的编程)的高中 or 大学生 leetcode 介绍 leetcode 可以说是 cs 最核心的一门"课程"了,虽然不是大学开设的,但基本上每一个现代的高水平的程序 ...
- pythonopencv算法_opencv python 光流法
光流法 光流是由对象或相机的移动引起的两个连续帧之间的图像对象的明显运动的模式.它是2D矢量场,其中每个矢量是位移矢量,表示从第一帧到第二帧的点的移动. 上图表示的是一个球在连续的5帧图像中的运动,箭 ...
- 光流法 python_CV学习笔记(八):光流法原理
在之前的几篇关于OpenCV的文章中我集中介绍了OpenCV中比较常用的操作和函数.在我们基础的学习中,这些函数其实在图像进行预操作的过程中已经够用了.因此在之后的文章中,我们要继续深入使用OpenC ...
- 稀疏光流python_opencv python 光流法
光流法 光流是由对象或相机的移动引起的两个连续帧之间的图像对象的明显运动的模式.它是2D矢量场,其中每个矢量是位移矢量,表示从第一帧到第二帧的点的移动. 上图表示的是一个球在连续的5帧图像中的运动,箭 ...
- Python与Matlab算法学习一文通(快速排序算法)(更新中)
想利用一些空余时间学一学python与matlab,与同学建立不知道能坚持多久的学习联盟,每周一部分题目,利用一周时间完成原理文档与程序编写.由于主要研究方向为其他方向,因此只会利用很少的空闲时间来学 ...
- 车流检测之halcon光流法算法实现
* This example program shows how to use optical_flow_mg to compute the optical flow in an image sequ ...
- python数据结构与算法学习之基本结构
目录 线性结构Linear Structure 栈Stack 抽象数据类型Stack(ADT Stack) 栈的应用:简单括号匹配 栈的应用:通用括号匹配 栈的应用:进制转换 表达式转换 中缀表达法 ...
- 拉格朗日差值法----算法学习
一.定义: 对某个多项式函数,已知有给定的k + 1个取值点: 其中对应着自变量的位置,而对应着函数在这个位置的取值. 假设任意两个不同的xj都互不相同,那么应用拉格朗日插值公式所得到的拉格朗日插值多 ...
- OpenCV学习笔记(二十六)——小试SVM算法ml OpenCV学习笔记(二十七)——基于级联分类器的目标检测objdect OpenCV学习笔记(二十八)——光流法对运动目标跟踪Video Ope
OpenCV学习笔记(二十六)--小试SVM算法ml 总感觉自己停留在码农的初级阶段,要想更上一层,就得静下心来,好好研究一下算法的东西.OpenCV作为一个计算机视觉的开源库,肯定不会只停留在数字图 ...
最新文章
- Mastering Algorithms with C中文版附带源码说明
- 真没想到中国有这么猛的软件,杀伤力太强了!
- 创业还需要开发 App 么?
- 《LeetCode力扣练习》第155题 最小栈 Java
- labelimg选中高亮
- Linux man 使用详解(转)
- WebAssembly的Qt
- python selenium下载,在python中通过Selenium Webdriver下载文件
- opencv模糊图像变清晰_opencv-python 4.2图像模糊
- 蔚来汽车回应“十四万元补胎”纠纷:车主未及时报案 除轮胎外底盘也严重受损...
- java voip 的sip服务器搭建_SIP服务器,搭建自己的VoIP平台 | 学步园
- jdk6或者7Base64转码与解码
- labelme批量json转png数据集教程
- 超级玛丽 Super Mario java基础小游戏:基于JAVA面向对象实现的超级马里奥(Super Mario)游戏(简单小游戏,仅仅使用Java面向对象基础实现(附上源码))
- 怎么删除网络共享多余的计算机,win10系统删除网络共享中多余的计算机的图文教程...
- 8.用C/C++实现一个科学计算器———(超级详细完整,包含C/C++版本和Qt版本)
- 推荐一个动画框架Lottie
- Java项目自动生成接口文档
- 研二小硕的艰难实习路
- 揭秘Mysql事务隔离级别之可重复读
热门文章
- 爱快支持服务器网卡嘛,虚拟机安装爱快软路由,跟我一起来测试,单网卡安装教程...
- 新一配:创建数据透视表时的注意事项【转载】
- Atitit MP3元数据抽取结果 音乐信息检索 取出了重复和英文的数据 一共368个。。 /bookmarksHtmlEverythingIndexPrj/src/apkg/songlistC
- pyodbc mysql_Robot Framework 通过pyodbc连接Mysql
- 关于 小程序 传值的 几个方法
- 基于二分查询树(BinarySearchTrees)实现的键值对表(symbole-table)
- RS485设计技巧TOP10
- ctc decoder
- 免费云服务器(阿贝云服务器入门)(仅适用于windows server系统)
- 小程序与MySQL数据库的交互_微信小程序数据库交互如何做到?