主要内容

利用点特征匹配实现视频稳定

这个例子展示了如何稳定从一个抖动的平台上捕获的视频。稳定视频的一种方法是跟踪图像中的一个显著特征,并将其作为一个定位点来消除与它相关的所有扰动。然而,这一过程必须通过了解第一个视频帧中该显著特征的位置来引导。在这个例子中,我们探索了一种视频稳定的方法,没有任何这样的工作先天的知识。它改为自动搜索视频序列中的“背景平面”,并使用其观察失真来校正相机运动。

这种稳定算法涉及两个步骤。首先,我们确定使用视频序列的所有相邻帧之间的仿射图像变换estimateGeometricTransform2D用于两个图像之间点对应的函数。第二,我们扭曲视频帧以实现稳定的视频。我们将使用计算机视觉工具箱™,用于算法和显示。

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

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

文件名=“shaky_car.avi”;hvideosrc = Videoreader(文件名);IMGA = RGB2GRAY(IM2Single(ReadFrame(HVideOSRC)));%读入IMGA的第一帧imgB = rgb2gray (im2single (readFrame (hVideoSrc)));%读入IMGB的第二帧图;imshowpair (imgA imgB,“蒙太奇”);标题(['框架A'repmat (' ',[170]),B帧的]);

图;imshowpair (imgA imgB,“ColorChannels”'红星');标题(颜色合成(框架A =红色,框架B =青色));

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

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

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

来自两个帧的检测点在下图中示出。观察它们中有多少覆盖相同的图像特征,例如沿树线的点,大型道路标志的角落,以及汽车的角落。

ptThresh = 0.1;pointsA = detectFASTFeatures (imgA,'mincontrast',ptthresh);指点= detectfatfeatures(IMGB,'mincontrast',ptthresh);%显示图像A和图像B中的角图;imshow (imgA);持有;绘图(指点);标题(在一个角落的);

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

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

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

%提取角落的怪胎描述符[特征,指点] =提取物(IMGA,Poipta);[特点,点,点] =提取物(IMGB,点);

匹配功能在当前和上一个框架中找到。由于怪胎描述符是二进制的,因此matchfeatures.函数使用汉明距离找到相应的点。

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

下图显示的是与上面相同的颜色合成,但添加了来自框架A的红色点和来自框架B的绿色点。点与点之间用黄线表示由上述程序选择的对应关系。这些通信中有许多是正确的,但也有大量的异常值。

图;ShowMatchedFeatures(IMGA,IMGB,Poipta,Pointb);传奇(“一个”“B”);

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

在前一步中获得的许多点对应关系是不正确的。但是,我们仍然可以使用M估算器样本共识(MSAC)算法来得出两个图像之间的几何变换的强大估计,这是RANSAC算法的变型。MSAC算法在其中实现estimateGeometricTransform2D函数。这个函数,当给定一组点对应时,将搜索有效的内对应。然后从这些推导出仿射变换,使第一组点的内嵌线与第二组点的内嵌线匹配得最接近。这个仿射变换将是如下形式的3 × 3矩阵:

[A_1 A_3 0;A_2 A_4 0;t_x t_y 1]

的参数 一个 定义变换的刻度,旋转和剪切效果,而参数 t 是翻译参数。这个变换可以用来扭曲图像,这样它们对应的特征将被移动到相同的图像位置。

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

[tform, inlierIdx] = estimategeometritransform2d (...pointsB pointsA,仿射的);点= pointb(inlieridx,:);potiptam = pointipta(inlieridx,:);IMGBP = IMWARP(IMGB,TForm,'OutputView'imref2d(大小(imgB)));pointsBmp = transformPointsForward(tform, pointsBm.Location);

下面是一个彩色合成显示帧a与重新投影的帧B重叠,以及重新投影的点对应。结果非常好,内部对应几乎完全一致。两张照片的核心对齐得很好,以至于红青色的合成图在那个区域几乎变成纯黑白。

注意,内部的对应关系都是在图像的背景中,而不是在前景中,前景本身没有对齐。这是因为背景特征足够遥远,它们的行为就好像它们在一个无限遥远的平面上。因此,即使仿射变换仅限于改变成像平面,在这里这足以对齐两幅图像的背景平面。此外,如果我们假设背景平面在帧间没有明显移动或改变,那么这个变换实际上是捕捉相机运动。因此,纠正这将稳定视频。只要摄像机在帧间的运动足够小,或者相反,如果视频帧率足够高,这个条件就会保持。

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

步骤5.变换近似和平滑

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

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

我们可以使用上面的仿射变换的所有六个参数,但是,对于数值简单和稳定性,我们选择重新拟合矩阵作为更简单的刻度转换转换。与完整仿射变换的六个相比,这仅具有四个自由参数:一个比例因子,一个角度和两种翻译。这个新的变换矩阵是表单:

[s * cos (ang) s * sin (ang) 0;* 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 =[[缩放*[cos() -sin();罪(θ)因为(θ)];...[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®函数中CVEXESTSTABILIZIONTFORM.这个函数CVEXTFORMTOSRT.还将一般仿射变换转换为比例-旋转-平移变换。

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

有了这段代码,你也可以去掉早期退出条件,让循环处理整个视频。

%将视频源重置为文件的开头。阅读(HVIDEOSRC,1);hvplayer = Vision.videoplayer;%创建视频查看器%处理视频中的所有帧movmean = rgb2gray(Im2single(ReadFride(HVideosrc)));IMGB = movmean;IMGBP = IMGB;纠正剧= IMGBP;II = 2;hcumulative =眼睛(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);movmean = movmean /(II-2);%在这里调用对象上的发布方法以关闭任何打开的文件%和释放内存。释放(HVPlayer);

在计算过程中,我们计算了原始视频帧和修正后的帧的平均值。这些平均值在下面并排显示。左图显示的是原始输入帧的均值,证明了原始视频中存在很大的失真。然而,右边校正后的帧的平均值显示的图像核心几乎没有失真。当前景细节被模糊时(这是汽车向前运动的必然结果),这显示了稳定算法的有效性。

图;imshowpair(Movemean,纠正怪,“蒙太奇”);标题([“原始输入的意思”repmat (' ',[1 50]),'纠正序列意味着']);

参考文献

[1] Tordoff, B;穆雷,DW。“运动估计的引导采样和共识。”计算机视觉,2002年欧洲会议。

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

[3] Litvin,;康拉德,J;卡尔,WC。使用卡尔曼滤波和拼接的概率视频稳定电子成像、图像和视频通信学术研讨会,2003。

[4] Matsushita,Y;OFEK,E;唐,x;Shum,hy。“全帧视频稳定”。Microsoft®研究亚洲。CVPR 2005。