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

文章目录

基本相机移动

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

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

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

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

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

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

区分动作的核心思想

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

相关推荐
高效办公能手11 小时前
图片翻译器,分享四款直接翻译图片的软件!
数码相机
shuxianshrng21 小时前
鹰眼降尘系统怎么样
大数据·服务器·人工智能·数码相机·物联网
鬼臾区1 天前
展锐平台手机camera 软硬件架构
数码相机·智能手机·硬件架构
光学测量小菜鸡1 天前
线结构光测量系统标定--导轨
数码相机·算法·3d
光电的一只菜鸡3 天前
相机光学(三十八)——VCM(Voice Coil Motor)音圈马达
数码相机
Hali_Botebie3 天前
【相机方案(2)】V4L2 支持相机图像直接进入GPU内存吗?DeepStream 确实可以将图像数据高效地放入GPU内存进行处理!
数码相机
Zhangci]4 天前
Vm软件安装_链接相机
数码相机
文 丰4 天前
【Android Studio】API 29(即Android 10)或更高版本,在程序启动时检查相机权限,并在未获取该权限时请求它
android·数码相机·android studio
格林威5 天前
Baumer工业相机堡盟工业相机如何通过BGAPISDK使用短曝光功能(曝光可设置1微秒)(C语言)
c语言·开发语言·人工智能·数码相机·计算机视觉
仰望大佬0075 天前
HalconDotNet中的图像视频采集
数码相机·计算机视觉·c#·音视频·halcon