视频稳定的最佳算法
Posted
技术标签:
【中文标题】视频稳定的最佳算法【英文标题】:Best algorithm for video stabilization 【发布时间】:2014-05-20 21:14:57 【问题描述】:我正在创建一个程序来稳定视频流。目前,我的程序基于相位相关算法工作。我正在计算两个图像之间的偏移量 - 基本图像和当前图像。接下来我根据新坐标校正当前图像。该程序有效,但结果并不令人满意。相关链接您可能会发现处理后的视频看起来不受欢迎,并且整个视频抖动变得更糟。Orininal videoUnshaked video 我目前的认识是: 计算图像之间的偏移量:
Point2d calculate_offset_phase_optimized(Mat one, Mat& two)
if(two.type() != CV_64F)
cvtColor(two, two, CV_BGR2GRAY);
two.convertTo(two, CV_64F);
cvtColor(one, one, CV_BGR2GRAY);
one.convertTo(one, CV_64F);
return phaseCorrelate(one, two);
根据这个坐标移动图像:
void move_image_roi_alt(Mat& img, Mat& trans, const Point2d& offset)
trans = Mat::zeros(img.size(), img.type());
img(
Rect(
_0(static_cast<int>(offset.x)),
_0(static_cast<int>(offset.y)),
img.cols-abs(static_cast<int>(offset.x)),
img.rows-abs(static_cast<int>(offset.y))
)
).copyTo(trans(
Rect(
_0ia(static_cast<int>(offset.x)),
_0ia(static_cast<int>(offset.y)),
img.cols-abs(static_cast<int>(offset.x)),
img.rows-abs(static_cast<int>(offset.y))
)
));
int _0(const int x)
return x < 0 ? 0 : x;
int _0ia(const int x)
return x < 0 ? abs(x) : 0;
我正在查看文档作者稳定器 YouTube 和基于角点检测的算法似乎很有吸引力,但我并不完全清楚它是如何工作的。 所以我的问题是如何有效地解决这个问题。 条件之一 - 程序将在较慢的计算机上运行,因此可能不适合繁重的算法。 谢谢! 附言 对于文本中的任何错误,我深表歉意 - 这是自动翻译。
【问题讨论】:
您的目标是什么类型的视频?只是人造图像(场景实际上是一个平面)或像素可能处于不同深度的真实视频?你想纠正什么动作?最需要平滑的运动,但高加速度的运动通常是噪音。 目标视频示例:youtube.com/watch?v=Ta8w_nzuMkU 我当前稳定器的结果:youtube.com/watch?v=-0p-uJEacVI 最高优先级是消除平面相机移动中的抖动。旋转和缩放是可选的。 我可以想象场景的深度可能是一个真正的问题(远像素不会像近像素那样移动)。我不知道这通常是如何完成的,但我会这样做:使用两个或更多图像估计每个点的 3D 位置。也估计 3D 摄像机的运动。平滑相机路径(例如使用盒子过滤器)并重新渲染场景,填充可能出现的任何漏洞。我不确定纯翻译是否足够。 【参考方案1】:您可以在每一帧中使用SIFT 等图像描述符,并在帧之间计算robust matches。然后您可以计算帧之间的homography 并使用它来对齐它们。与使用密集相关性相比,使用稀疏特征可以实现更快的实现。
或者,如果您知道camera parameters,您可以calculate 3D positions 点和相机,并将图像重新投影到稳定的投影平面上。结果,您还获得了场景的sparse 3D reconstruction(有点不精确,通常需要optimized 才能使用)。这就是例如Autostitch 可以,但是很难实现。
注意,相机参数也可以是calculated,不过这样就更难了。
【讨论】:
感谢您的回答!我是这个领域的新手,所以我遇到了一些误解。有我的代码:detector.detect(base_frame, keypoints_base); detector.detect(current_frame, keypoints_cur); extractor.compute(..., keypoints_base, descriptors_base); extractor.compute(..., keypoints_cur, descriptors_cur); matcher.knnMatch(description_base, description_cur, matches, 2);
比我过滤最佳匹配并执行此操作:homography = findHomography(k_base, k_cur, CV_RANSAC);
但下一步我应该做什么? warpAffine 不采用这个单应性 3x3,只有 2x3。
改用warpPerspective
(见docs.opencv.org/modules/imgproc/doc/…)。
我尝试实现了这个算法,但结果并不理想:video我提醒你,帧是和固定帧比较的。在这种情况下,它是第一个视频帧。 Full code
好吧,如果您的视频从第一帧开始平移,那么您不可能将其用作参考,因为当帧之间没有共同特征时,将无法计算转换(这显然发生在你的视频中)。您需要使用浮动引用。
浮动引用将通过计算连续帧之间的转换并堆叠转换来实现。同时,在每一步,变换堆栈都被插值单位矩阵,使视图不会随着时间而消失。这应该会产生平稳的运动。【参考方案2】:
OpenCV 只需 3 行代码就可以完成(绝对是最短的方法,甚至可能是最好的方法):
t = estimateRigidTransform(newFrame, referenceFrame, 0); // 0 means not all transformations (5 of 6)
if(!t.empty())
warpAffine(newFrame, stableFrame, t, Size(newFrame.cols, newFrame.rows)); // stableFrame should be stable now
你可以通过修改矩阵 t 来关闭某种变换,这样可以得到更稳定的结果。这只是核心思想,然后您可以按照您想要的方式对其进行修改:更改参考框架,从矩阵 t 平滑转换参数集等。
【讨论】:
以上是关于视频稳定的最佳算法的主要内容,如果未能解决你的问题,请参考以下文章