使用OpenCV进行视频稳定化

37

我有一个包含移动物体的移动相机视频源,我想将视频稳定,使得所有静止的物体在视频中保持不动。如何使用OpenCV实现这一目标?

例如,如果我有两个图像prev_framenext_frame,我该如何转换next_frame以使视频看起来静止?

8个回答

42

我可以建议以下解决方案:

  1. 使用本地高级特征:OpenCV包括SURF,所以:对于每一帧,提取SURF特征。然后建立特征Kd-Tree(也在OpenCV中),然后将每两个连续的帧匹配以找到对应特征的一对。将这些对输入cvFindHomography中以计算这些帧之间的单应性矩阵。根据(合并的...)单应性矩阵扭曲帧以稳定画面。据我所知,这是一种非常稳健和精密的方法,但SURF的提取和匹配可能会比较慢。
  2. 如果您预期只有两帧之间有轻微的移动,则可以尝试使用“不太稳健”的特征来执行上述操作,例如使用Harris角点检测,并在两帧中最接近的角点之间建立一对,然后将其作为上述操作中的输入项传递给cvFindHomography。这样可能会更快,但不太稳健。
  3. 如果您将移动限制为平移,则可以将cvFindHomography替换为更简单的东西,以仅获取特征对之间的平移(例如平均值)。
  4. 如果您预计只有两帧之间的平移,则可以使用相位相关法(参见http://en.wikipedia.org/wiki/Phase_correlation)。OpenCV包括DFT / FFT和IFFT,请参阅链接的维基百科文章中的公式和说明。

编辑 我应该明确提到三点,以防万一:

  1. 基于单应性矩阵的方法可能非常准确,因此静止的物体将保持静止。但是,单应性矩阵包括透视畸变和缩放,因此结果可能看起来有点...不寻常(甚至对于某些快速运动可能会变形)。尽管是精确的,但这可能不太视觉上令人愉悦;因此,最好将其用于进一步处理或例如取证。但您应该尝试一下,有些场景/运动可能会非常令人愉悦。
  2. 据我所知,至少有几个免费的视频稳定工具使用相位相关法。如果您只想“消除”相机抖动,则可能更适合使用该方法。
  • 在这个领域进行了许多研究。您可以在一些论文中找到更复杂的方法(尽管它们可能需要不止OpenCV)。

  • 很棒的回答!一个不错的列表。我不知道相位相关。谢谢! - Jean-Philippe Jodoin

    17

    OpenCV有estimateRigidTransform() 和warpAffine()两个函数,可以很好地处理这种问题。

    它的使用方法非常简单:

    Mat M = estimateRigidTransform(frame1,frame2,0)
    warpAffine(frame2,output,M,Size(640,480),INTER_NEAREST|WARP_INVERSE_MAP) 
    
    现在,output包含最佳对齐以适应frame1frame2的内容。 对于大的偏移,M将是一个零矩阵,或者根据OpenCV版本可能根本不是矩阵,因此您需要过滤掉它们并不应用它们。我不确定那有多大;也许是帧宽度的一半,也许更多。 estimateRigidTransform的第三个参数是一个布尔值,指示其是否还要应用任意仿射矩阵或限制为平移/旋转/缩放。为了稳定来自相机的图像,您可能只想要后者。实际上,对于相机图像稳定,您可能还要通过仅正常化旋转和平移来从返回的矩阵中删除任何缩放。 此外,对于移动相机,您可能需要通过时间取样M并计算平均值。 以下是关于estimateRigidTransform()和warpAffine()的更多信息链接:estimateRigidTransform()warpAffine()

    Size 方法在哪个库中? - user3731622

    14

    9
    我从这里的回答中复制了我的答案。 如何稳定网络摄像头视频?
    昨天我在这个主题上做了一些工作(使用Python),主要步骤如下:
    1. 使用cv2.goodFeaturesToTrack查找好的角点。
    2. 使用cv2.calcOpticalFlowPyrLK跟踪角点。
    3. 使用cv2.findHomography计算单应矩阵。
    4. 使用cv2.warpPerspective转换视频帧。
    但是现在的结果不太理想,也许我应该选择SIFT keypoints而不是goodFeatures
    来源:

    enter image description here

    稳定汽车:

    enter image description here


    1
    你知道如何修复黑色区域吗? - a.masri

    3

    这里已经有一个好的答案,但使用了有点老旧的算法,而我开发了可以解决类似问题的程序,所以我添加了额外的答案。

    1. 首先,您应该使用像SIFT、SURF算法这样的特征提取器从图像中提取特征。在我的情况下,FAST+ORB算法是最好的选择。如果您需要更多信息,请参考此文献
    2. 在获取图像的特征之后,您应该找到匹配的图像特征。有几种匹配器,但暴力匹配器也不错。如果暴力匹配在您的系统上速度较慢,您可以使用像KD-Tree这样的算法。
    3. 最后,您应该获得几何变换矩阵,这会最小化转换点的误差。您可以在这个过程中使用RANSAC算法。您可以使用OpenCV开发所有这些过程,而我已经在移动设备上进行了开发。请查看此存储库

    3
    这是一个棘手的问题,但我能想到一个比较简单的解决方案。
    1. next_frame 按任意量进行移动/旋转。
    2. 使用背景减法 threshold(abs(prev_frame-next_frame_rotated)) 来查找静态元素。您需要尝试不同的阈值值。
    3. 查找 min(template_match(prev_frame_background, next_frame_rotated_background))
    4. 记录最接近匹配的移动/旋转,并将其应用于 next_frame
    这种方法在多帧连续处理时效果不佳,因此您需要考虑使用背景累加器,以便算法查找的背景随时间保持相似。

    3
    我应该补充以下内容来完善zerm's answer。如果选择一个静止的物体,然后使用zerm的方法(1)处理单个物体,将简化您的问题。如果您找到一个静止的物体并对其进行校正,则可以安全地假设其他静止的物体也会看起来稳定。
    虽然这种方法对于您的复杂问题确实有效,但您将遇到以下问题:
    - 检测和单应性估计有时会因各种原因失败:遮挡、突然移动、运动模糊、严重的光照差异。您将不得不寻找处理它的方法。 - 您的目标对象可能会被遮挡,这意味着在该帧上检测失败,您将不得不处理遮挡,这本身就是一个整个研究课题。 - 根据您的硬件和解决方案的复杂性,使用SURF可能会有一些实时结果方面的困难。您可以尝试opencv的gpu实现或其他更快的特征检测器,如ORB、BRIEF或FREAK。

    0

    背景: 我正在进行一个研究项目,试图计算一个人在排队等候时需要多长时间才能到达柜台。我首先需要的是录像素材,于是我去了校园并记录下了一些游客在排队购票时的移动情况。直到这个时候,我还不知道如何计算排队时间以及在录制素材时应该注意什么预防措施。最终,我发现我所记录的所有素材都是用抖动的相机拍摄的。因此,在这一点上,我首先需要稳定视频,然后才能开发其他解决方案来计算排队时间。

    使用模板匹配进行视频稳定

    • 查找静态对象,例如柱子、门或其他你知道不应该移动的物体
    • 使用模板匹配来计算每个连续帧中静态对象(相对于帧边界)位置变化的偏移量。
    • 将每个帧与偏移值进行平移,例如tx和ty。

    结果素材:

    演示这种技术结果的Gif动画

    正如您在gif中所看到的,选定的静态对象相对于帧边界保持静态,而运动可以通过从帧边缘填充黑色来看到。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接