点击上方“计算机视觉life”,选择“星标”
快速获得最新干货
本文转自OpenCV学堂
这篇文章分享了一个视频防抖的策略,这个方法同样可以应用到其他领域,比如常见的关键点检测,当使用视频测试时,效果就没有demo那么好,此时可以考虑本文的方法去优化。
分享这些demo并不一定所有人都会用到,但是在解决实际问题的时候,可以提供一个思路去解决问题。希望能给我一个三连,鼓励一下哈
在这篇文章中,我们将学习如何使用OpenCV库中的点特征匹配技术来实现一个简单的视频稳定器。我们将讨论算法并且会分享代码(python和C++版),以使用这种方法在
OpenCV中设计一个简单的稳定器。
视频中低频摄像机运动的例子
视频防抖是指用于减少摄像机运动对最终视频的影响的一系列方法。摄像机的运动可以是平移(比如沿着x、y、z方向上的运动)或旋转(偏航、俯仰、翻滚)。
视频防抖的应用
对视频防抖的需求在许多领域都有。
这在消费者和专业摄像中是极其重要的。因此,存在许多不同的机械、光学和算法解决方案。即使在静态图像拍摄中,防抖技术也可以帮助拍摄长时间曝光的手持照片。
在内窥镜和结肠镜等医疗诊断应用中,需要对视频进行稳定,以确定问题的确切位置和宽度。
同样,在军事应用中,无人机在侦察飞行中捕获的视频也需要进行稳定,以便定位、导航、目标跟踪等。同样的道理也适用于机器人。
视频防抖的不同策略
视频防抖的方法包括机械稳定方法、光学稳定方法和数字稳定方法。下面将简要讨论这些问题:
机械视频稳定:机械图像稳定系统使用由特殊传感器如陀螺仪和加速度计检测到的运动来移动图像传感器以补偿摄像机的运动。光学视频稳定:在这种方法中,不是移动整个摄像机,而是通过镜头的移动部分来实现稳定。这种方法使用了一个可移动的镜头组合,当光通过相机的镜头系统时,可以可变地调整光的路径长度。数字视频稳定:这种方法不需要特殊的传感器来估计摄像机的运动。主要有三个步骤:1)运动估计2)运动平滑,3)图像合成。第一步导出了两个连续坐标系之间的变换参数。第二步过滤不需要的运动,在最后一步重建稳定的视频。
在这篇文章中,我们将学习一个快速和鲁棒性好的数字视频稳定算法的实现。它是基于二维运动模型,其中我们应用欧几里得(即相似性)变换包含平移、旋转和缩放。
OpenCV Motion Models
正如你在上面的图片中看到的,在欧几里得运动模型中,图像中的一个正方形可以转换为任何其他位置、大小或旋转不同的正方形。它比仿射变换和单应变换限制更严格,但对于运动稳定来说足够了,因为摄像机在视频连续帧之间的运动通常很小。
使用点特征匹配实现视频防抖
该方法涉及跟踪两个连续帧之间的多个特征点。跟踪特征允许我们估计帧之间的运动并对其进行补偿。
下面的流程图显示了基本步骤。
我们来看看这些步骤。
第一步:设置输入和输出视频首先,让我们完成读取输入视频和写入输出视频的设置。代码中的注释解释每一行。
Python
# Import numpy and OpenCVimport numpy as npimport cv2# Read input videocap = cv2.VideoCapture('video.mp4') # Get frame countn_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # Get width and height of video streamw = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# Define the codec for output videofourcc = cv2.VideoWriter_fourcc(*'MJPG')# Set up output videoout = cv2.VideoWriter('video_out.mp4', fourcc, fps, (w, h))
C++
// Read input video VideoCapture cap("video.mp4"); // Get frame count int n_frames = int(cap.get(CAP_PROP_FRAME_COUNT)); // Get width and height of video stream int w = int(cap.get(CAP_PROP_FRAME_WIDTH)); int h = int(cap.get(CAP_PROP_FRAME_HEIGHT)); // Get frames per second (fps) double fps = cap.get(CV_CAP_PROP_FPS); // Set up output video VideoWriter out("video_out.avi", CV_FOURCC('M','J','P','G'), fps, Size(2 * w, h));
第二步:读取第一帧并将其转换为灰度图
对于视频稳定,我们需要捕捉视频的两帧,估计帧之间的运动,最后校正运动。
Python
# Read first frame_, prev = cap.read() # Convert frame to grayscaleprev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
C++
// Define variable for storing frames Mat curr, curr_gray; Mat prev, prev_gray; // Read first frame cap << prev; // Convert frame to grayscale cvtColor(prev, prev_gray, COLOR_BGR2GRAY);
第三步:寻找帧之间的移动
这是算法中最关键的部分。我们将遍历所有的帧,并找到当前帧和前一帧之间的移动。没有必要知道每一个像素的运动。欧几里得运动模型要求我们知道两个坐标系中两个点的运动。但是在实际应用中,找到50-100个点的运动,然后用它们来稳健地估计运动模型是一个好方法。