主要内容

使用点特征匹配的视频稳定

这个例子展示了如何稳定从一个紧张的平台捕获的视频。稳定视频的一种方法是跟踪图像中的一个显著特征,并将其作为锚点来抵消与它相关的所有扰动。然而,在引导这个过程时,必须知道在第一个视频帧中这个显著特征在哪里。在这个例子中,我们探索了一种不需要任何这样的方法的视频稳定先天的相反,它会自动搜索视频序列中的“背景平面”,并使用观察到的失真来校正摄像机的运动。

该稳定算法包括两个步骤。首先,我们使用estimateGeometricTransform2D函数用于两个图像之间的点对应。其次,我们扭曲视频帧来实现稳定的视频。我们将使用计算机视觉工具箱™,用于算法和显示。

步骤1。从电影文件中读取帧

这里我们读一个视频序列的前两帧。我们将它们作为强度图像读取,因为稳定算法不需要颜色,而且使用灰度图像可以提高速度。下面我们将两个帧并排显示,并生成一个红青色组合来说明它们之间的像素差异。很明显,这两个画面之间有很大的垂直和水平偏移。

文件名=“shaky_car.avi”;hVideoSrc=VideoReader(文件名);imgA=rgb2gray(im2single(readFrame(hVideoSrc));%将第一帧读入imgAimgB = rgb2gray (im2single (readFrame (hVideoSrc)));%将第二帧读入imgB图形imshowpair(imgA、imgB、,“蒙太奇”); 头衔([“帧A”repmat (' ',[1 70]),B帧的]);

图:imshowpair(imgA、imgB、,“ColorChannels”,“红青色”);标题('Color composite (frame A =红色,frame B =青色)');

步骤2。收集每一帧的突出点

我们的目标是确定一个转换,将纠正两个帧之间的失真。我们可以使用estimateGeometricTransform2D函数,它将返回一个仿射变换。作为输入,我们必须为这个函数提供两帧之间的一组点对应。为了生成这些通信,我们首先从两个帧中收集感兴趣的点,然后选择它们之间可能的通信。

在这个步骤中,我们为每一帧生成候选点。为了使这些点有最好的机会在另一帧中有相应的点,我们希望在图像显著特征(如角)周围有点。为此,我们使用detectFASTFeatures函数,实现了最快的角点检测算法之一。

两个帧中检测到的点如下图所示。观察其中有多少覆盖了相同的图像特征,例如沿树线的点、大型路标的拐角和汽车的拐角。

ptThresh = 0.1;pointsA = detectFASTFeatures (imgA,“对比度”,ptThresh);pointsB=检测FastFeatures(imgB,“对比度”,ptThresh);%显示图像A和B中的角。图;imshow (imgA);持有; 绘图(点SA);头衔(在一个角落的);

图;imshow (imgB);持有;情节(pointsB);标题(“B中的角”);

步骤3。选择点之间的对应关系

接下来我们选择上面推导的点之间的对应关系。对于每个点,我们提取一个以其为中心的快速视网膜关键点(FREAK)描述符。由于FREAK描述符是二进制的,所以我们使用的点之间的匹配代价是汉明距离。假定坐标系A和坐标系B中的点是匹配的。注意,没有唯一性约束,所以坐标系B中的点可以对应坐标系A中的多个点。

%提取角点的异常描述符[featuresA,pointsA]=提取特征(imgA,pointsA);[featuresB,pointsB]=提取特征(imgB,pointsB);

匹配在当前帧和前一帧中找到的特征。由于畸形描述符是二进制的,因此匹配特征函数使用汉明距离来查找相应的点。

indexPairs = matchFeatures(featuresA, featuresB);pointsA = pointsA(indexPairs(:, 1),:);pointb = pointb (indexPairs(:, 2),:);

下面的图片显示了上面给出的相同的颜色组合,但是添加了来自框架A的点(红色)和来自框架B的点(绿色)。在点之间画黄线,以显示上述程序选择的对应关系。这些对应中有许多是正确的,但也有相当数量的异常值。

图;显示匹配的特征(imgA、imgB、pointsA、pointsB);图例(“一个”,“B”);

步骤4。从噪声通信中估计变换

在前一步中获得的许多点对应是不正确的。但是,我们仍然可以使用M估计样本一致性(MSAC)算法(RANSAC算法的一个变体)推导两幅图像之间几何变换的稳健估计。MSAC算法在estimateGeometricTransform2D函数。当给定一组点对应时,该函数将搜索有效的内部对应。然后,它将从这些派生出仿射变换,使第一组点的内嵌线与第二组点的内嵌线最接近匹配。这个仿射变换将是一个3 × 3的矩阵,形式如下:

(a_1 a_3 0;a₂a_4 0;t_x t_y 1]

的参数 一个 定义变换的缩放、旋转和剪切效果,同时 t 是翻译参数。这个变换可以用来扭曲图像,使其相应的特征将被移动到相同的图像位置。

仿射变换的一个局限性是它只能改变成像平面。因此,它不适用于寻找3d场景的两帧之间的一般失真,例如这段从移动的汽车上拍摄的视频。但它确实在某些条件下起作用,我们稍后将描述。

[tform, inlierIdx] = estimateGeometricTransform2D(...pointsB pointsA,仿射的);pointsBm=pointsB(inlierIdx,:);pointsAm=pointsA(inlierIdx,:);imgBp=imwarp(imgB,tform,“OutputView”imref2d(大小(imgB)));pointbmp = transformpointforward (tform, pointbmp . location);

下面是一个颜色合成图,显示了帧a与重投影帧B的叠加,以及重投影的对应点。结果是极好的,与早期的对应几乎完全一致。图像的核心都对齐得很好,这样红青色的复合色在那个区域几乎变成纯黑白。

注意,早期的对应都在图像的背景中,而不是在前景中,前景本身并没有对齐。这是因为背景特征是足够远的,他们的行为就像他们在一个无限远的平面上。因此,即使仿射变换仅限于改变成像平面,在这里,这足以对齐两个图像的背景平面。此外,如果我们假设背景平面在帧之间没有移动或显著改变,那么这个变换实际上捕获了相机的运动。因此,纠正这一点将稳定视频。只要摄像机在帧间的运动足够小,或者相反,如果视频帧率足够高,这种情况就会持续。

图;showMatchedFeatures(imgA, imgBp, pointsAm, pointsBmp);传奇(“一个”,“B”);

第五步。变换逼近与平滑

给定一组视频帧 T , 0 , 1 , 2 ... ,我们现在可以使用上述程序来估计所有帧之间的失真 T T + 1 作为仿射变换, H .即帧的累积变形 相对于第一帧,将是前面所有帧间变换的乘积,或

H c u u l 一个 t v e , H j 0 - 1

我们可以使用上面仿射变换的所有六个参数,但是,为了数值的简单性和稳定性,我们选择将矩阵重新拟合为一个更简单的尺度旋转平移变换。与全仿射变换的六个参数相比,它只有四个自由参数:一个尺度因子、一个角度和两个平移。这种新的变换矩阵x的形式如下:

[s*cos(ang)s*-sin(ang)0;s*sin(ang)s*cos(ang)0;t_x t_y 1]

下面我们通过拟合上面得到的变换来展示这个转换过程 H 使用等效的缩放旋转平移, H 年代 R t .为了表明转换变换的误差是最小的,我们用两个变换重新投影B帧,并将下面的两幅图像显示为红青色合成。由于图像是黑白的,很明显,不同重投影之间的像素差异是可以忽略不计的。

%提取比例和旋转部分子矩阵。H = tform.T;R = H (1:2, 1:2);%从两个可能的arctan的均值计算θ=意味着([量化(R(2),(1)量化(R - R (3), (4))));%从两个稳定平均值的平均值计算比例尺scale = mean(R([1 4])/cos(theta));%翻译保持不变:平移= H(3, 1:2);%重建新的s-R-t变换:HsRt = [[scale*[cos(theta) -sin(theta));罪(θ)因为(θ)];...转换],[0 0 1]'];tformsRT=affine2d(HsRt);imgBold=imwarp(imgB,tform,“OutputView”,imref2d(大小(imgB));imgBsRt=imwarp(imgB,tformsRT,“OutputView”imref2d(大小(imgB)));图(2)中,clf;imshowpair (imgBold imgBsRt,“ColorChannels”,“红青色”),轴图像;标题(“仿射和s-R-t变换输出的颜色合成”);

步骤6。运行完整的视频

现在我们应用上面的步骤平滑一个视频序列。为便于阅读,上述估计两幅图像之间的变换的程序已放置在MATLAB®函数中CVEXestStabilizationForm.这个函数cvexTformToSRT还可将一般仿射变换转换为缩放-旋转-平移变换。

在每个步骤中,我们计算变换 H 在当前帧之间。我们将其拟合为s-R-t变换, H 年代 R t . 然后我们把它和累积变换结合起来, H c u u l 一个 t v e ,它描述了自第一帧以来摄像机的所有运动。平滑视频的最后两帧在视频播放器中显示为红青色合成。

使用这段代码,您还可以去掉早期退出条件,使循环处理整个视频。

%将视频源重置为文件的开头。读取(hVideoSrc,1);hVPlayer=vision.VideoPlayer;创建视频查看器%处理视频中的所有帧movMean=rgb2gray(im2single(读帧(hvidesrc));imgB=平均值;imgBp=imgB;修正平均值=imgBp;ii=2;H累积=眼睛(3);虽然hasFrame(hVideoSrc) && ii < 10%以新的框架阅读imgA = imgB;%z^-1imgAp=imgBp;%z^-1imgB = rgb2gray (im2single (readFrame (hVideoSrc)));movMean = movMean + imgB;%估计从帧A到帧B的变换,并拟合为s-R-tH = cvexEstStabilizationTform (imgA imgB);HsRt = cvexTformToSRT (H);Hcumulative = HsRt * Hcumulative;imgBp = imwarp (imgB affine2d (Hcumulative),“OutputView”,imref2d(大小(imgB));%显示为彩色合成与最后校正的帧步骤(hVPlayer、imfuse、imgAp、imgBp、,“ColorChannels”,“红青色”));correctedMean = correctedMean + imgBp;2 = 2 + 1;终止修正平均数=修正平均数/(ii-2);移动平均数=移动平均数/(ii-2);%在这里,您可以对对象调用release方法来关闭任何打开的文件%和释放内存。释放(hVPlayer);

在计算过程中,我们计算原始视频帧和校正帧的均值。这些平均值在下面并排显示。左边的图像是原始输入帧的均值,说明原始视频存在较大的失真。然而,右边校正帧的平均值显示的图像核心几乎没有失真。虽然前景细节已经被模糊(作为汽车前进的必要结果),这显示了稳定算法的效力。

图形imshowpair(平均值,修正平均值,“蒙太奇”); 头衔([“原始输入的意思”repmat (' ',[1 50]),“校正序列平均值”]);

参考文献

[1] 运动估计的引导采样和共识〉,欧洲计算机视觉会议,2002。

[2]李,肯塔基州;壮族,YY;陈,;Ouhyoung, M。“使用鲁棒特征轨迹的视频稳定。”国立台湾大学,2009。

[3] Litvin,;康拉德,J;卡尔,WC。"利用卡尔曼滤波和马赛克的概率视频稳定"电子图像、图像和视频通信技术研讨会,2003。

[4] 松下,Y;Ofek,E;Tang,X;Shum,HY.“全画幅视频稳定”,《微软®亚洲研究院》,CVPR 2005。