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

文章目录

基本相机移动

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

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

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

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

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

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

区分动作的核心思想

当我之前谈到不同的观点时,我的意思是在编写代码之前,我们需要弄清楚如何解释 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

相关推荐
只待花开14 小时前
ROS2 python编写 intel realsense D405相机节点通过launch.py启动多个相机并发送图像话题,基于pyrealsense2库
数码相机
KeyPan17 小时前
【ORB-SLAM3:相机针孔模型和相机K8模型】
数码相机
千穹凌帝19 小时前
基于深度学习多图像融合的屏幕缺陷检测方案
人工智能·深度学习·数码相机
传说故事2 天前
相机内外参知识
数码相机·相机·相机参数
妄想出头的工业炼药师2 天前
imu相机EKF
数码相机
合方圆~小文2 天前
工业摄像机基于电荷耦合器件的相机
人工智能·深度学习·数码相机·目标检测
资源补给站2 天前
大恒相机开发(1)—Python调用采集彩色图像并另存为本地
开发语言·python·数码相机
OAK中国_官方3 天前
四相机设计实现全向视觉感知的开源空中机器人无人机
数码相机·机器人·无人机
s_daqing3 天前
解锁BL后的K40降级
数码相机
Stark-C5 天前
相机与NAS的奇妙组合,如何使用相机拍照自动上传或备份到NAS
数码相机