使用光流进行相机运动估计

文章目录

基本相机移动

从我的非专业角度来看,尽管已知的摄像机运动有多种,但我们应该概述其中三种:

  • 一种是将摄像机安装在轨道上并移动------卡车、移动式摄影车、基座
  • 摄像机停留在同一位置并旋转------平移、倾斜
  • 改变变焦镜头的焦距------变焦

我们甚至可以更进一步,只保留其中两个:

  • 摄影机移动------卡车、移动摄影车、基座

  • 相机保持在同一位置 --- 变焦、平移、倾斜

在这篇文章中,我们将使用平移和推车的示例来介绍区分移动的概念。对于其他组合(例如变焦和推车),可能需要采用不同的方法。

区分动作的核心思想

当我之前谈到不同的观点时,我的意思是在编写代码之前,我们需要弄清楚如何解释 panning 和 trucking 之间的区别。对于这两个,区别不是那么明显。

卡车运输时,场景中的所有物体都以相同的速度移动。然而,在平移时,距离摄像机较近的物体移动速度比距离摄像机较远的物体快。

因此,我们的想法是比较视频中不同物体的速度差异。以下是我逐步介绍的方法:

  • 计算一对帧上每个点的光流和平移值
  • 从排序后的翻译值两侧截断一些值------以消除异常值
  • 对其余值进行聚类(我使用 3 个聚类来将值彼此进一步分离)
  • 计算最小和最大聚类中心之间的差异
  • 如果差值大于某个阈值,视频就会发生平移,否则就会发生卡车移动。

它的效果出奇地好,但不幸的是也有其局限性。

视频中的某些物体在使用光流分析时可能非常棘手 - 例如天空或水。这些物体不会为算法提供要监控的精确点位置。

它还会受到视频中移动物体的影响,例如,如果视频中的人群四处奔跑或近景中只有一个人。因此,基本上,当有很多点以不同的速度向不同的方向移动时,它就会受到影响。

解决这一问题的方法之一是从帧中移除移动物体。方法是使用图像分割模型遮挡不需要的区域。也就是说,我们不考虑包含这些物体的区域的光流。

最后但并非最不重要的一点是,前景和背景之间的距离越远,算法的效果就越好。在靠近墙壁拍摄时,即使是人也很难确定其运动轨迹。在上面的例子中就很好地体现了这一点。

了解代码

OpenCV 视频读写入门指南

本节将对那些对想法的实现感兴趣的人和开始学习 OpenCV 的人有所帮助。本帖的实际代码可在此处找到。

该代码包含对帧中每个点的模式角和平移值的计算。这些值可用于确定摄像机运动的方向和速度。顺便说一下,在计算角度时,我们会记住原点的位置是在左下角(而不是 OpenCV 中的左上角)--这样似乎更方便。

假设我们要处理一段视频,并确定摄像机是如何移动的。我们想编写一段新视频,将算法的工作结果(或绘制光流本身)直接写入视频。

首先,我们需要截取一段视频,从中读取帧。

python 复制代码
cap = cv.VideoCapture(os.path.join(path, filename))

此类将视频文件的路径或摄像机的 ID 作为输入。要从对象读取帧,我们使用以下命令:

python 复制代码
ret, frame = cap.read()

该方法返回两个值。第一个是布尔值,如果读取成功则为 True(否则为 False),第二个是返回值(例如,如果相机已断开连接,或者视频文件中没有更多帧,则为 None)

我们还可以使用同一对象调用"get"方法。这个方法可以给我们提供很多信息。例如,我们可以提取原始视频的FPS值。

python 复制代码
cap.get(cv.CAP_PROP_FPS)

以下是我们可以使用此方法提取的信息的完整列表。

python 复制代码
outputStream = cv.VideoWriter(save_name, codec, frameRate, (int(cap.get(3)),int(cap.get(4))))

我们还需要事先初始化 VideoWriter 类对象。我们需要从原始视频中提取 fps 值和帧大小值。选择正确的编解码器可能有点棘手。如果您编写的视频是空的 - 您可以通过调整编解码器或输出视频格式进行实验。 这是有关保存视频的 OpenCV 教程。对我来说,工作的价值观如下:

python 复制代码
fps = int(cap.get(cv.CAP_PROP_FPS))
codec = cv.VideoWriter_fourcc(*'XVID')
frame_size = (int(cap.get(3)),int(cap.get(4))
outputStream = cv.VideoWriter("video.avi", codec, fps, frame_size)

最后,我们发现了一些有趣的事情。有多种算法可用于计算光流。我们将使用 Gunnar Farneback 算法来计算密集光流。如果您想了解该算法如何工作的细节,可以阅读这篇文章。

python 复制代码
flow = cv.calcOpticalFlowFarneback(img1, img2, None, 0.5, 3, 15, 3, 5, 1.2, 0)

该算法需要指定几个参数。您可以尝试选择适合您情况的值,也可以使用提供的一组值来更快地迭代整个过程。 这里是每个参数的描述。

您可以在此处找到其余代码。同时,这是两个不同视频的结果。条件几乎是理想的,因此算法正确运行也就不足为奇了。

参考

https://medium.com/@ikunyankin/camera-motion-estimation-using-optical-flow-ce441d7ffec

相关推荐
weixin_466485112 天前
halcon标定助手的使用
数码相机
诸葛务农4 天前
ToF(飞行时间)相机在人形机器人非接触式传感领域内的应用
数码相机·机器人
塞北山巅4 天前
相机自动曝光(AE)核心算法——从参数调节到亮度标定
数码相机·算法
美摄科技5 天前
相机sdk是什么意思?
数码相机
phyit5 天前
全景相机领域,影石何以杀出重围?
数码相机
鄃鳕5 天前
装饰器【Python】
开发语言·python·数码相机
聪明不喝牛奶5 天前
【已解决】海康威视相机如何升级固件
数码相机
PAQQ5 天前
1站--视觉搬运工业机器人工作站 -- 相机部分
数码相机·机器人
诸葛务农5 天前
人形机器人基于视觉的非接触式触觉传感技术
数码相机·机器人
moonsims6 天前
被动式热成像摄像机也称前视红外 (FLIR) 摄像机-Sierra-Olympia Technologies 中波红外摄像机
数码相机