打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Farneback光流
使用稀疏光流跟踪算法,可以实现关键点跟踪。大概流程为:首先在上一帧图像中检测出关键点,然后在下一帧图像中评估关键点位移量。如果下一帧图像以统一的方向偏移,则可以剔除该偏移以达到视频稳像效果。
关键点检测是稀疏光流跟踪基础,一般情况下,关键点为角点,边缘上的点由于孔径问题难以在系数光流中实现跟踪。使用稠密光流算法可以描述所有点(包括边缘上点)的运动情况,这在某些边缘较多的场景中,稠密光流算法更加便于描述物体运动。
Faerneback 算法使用多项式拟合平面方式评估图像中各个点的运动情况,其拟合平面方程为:
当图像发生平移后,平移前后拟合的二次多项式也同样存在一个平移关系:
,由于 
已知,则可以求解出 
在一维图像下,可使用下图表示:
上图中,拟合前后两帧图像相同位置附近区间的二次曲线,通过模型 
可求解偏移量 d。
以上跟踪精度取决于拟合函数精度,当拟合区间越小,更细小的变化可以被二次函数表现处理。但过小的拟合区间可能受到噪声影响,故需要选择一个合适的拟合区间。同时,可以使用多次拟合的方式来提升跟踪精度,第一次拟合时,下一帧图像拟合中心与上一帧图像拟合中心保持一致;当通过第一次拟合求解出偏移量后,使用偏移后位置作为下一帧图像拟合中心,可以求解更精确拟合函数,从而得到更精确跟踪精度。
通过金字塔分层方式可以跟踪到大偏移。首先使用较低分辨率跟踪各点偏移量,再以已经得到偏移量作为拟合中心,使用更高分辨率图像求解更精确偏移量,即可跟踪较大偏移。
在 opencv 中,使用 cv::calcOpticalFlowFarneback() 函数实现基于二次多项式拟合的稠密光流计算,其函数原型如下:
void cv::calcOpticalFlowFarneback(cv::InputArray preImg, cv::InputArray nextImg, cv::InputOutputArray flow,
double pyrScale, int levels, int winsize, int iterations, int polyN, double polySigma, int flags);
preImg, nextImg: 传入图像序列中前一帧与后一帧图像,图像格式均为8位单通道,且尺寸应该保持一致。
flow: 函数记录各点运动向量,图像格式位32位浮点双通道(CV_32FC2),图像尺寸与 preImg, nextImg 保持一致。
pyrScale: 表示金字塔各层缩减系数,一般使用 .5。
levels: 表示金字塔层数。
winsize: 在光流跟踪前,使用 winsize 窗口大小对图像平滑,避免噪声干扰;可将 flags 设置为 cv::OPTFLOW_FARNEBACK_GAUSSIAN 以使用 Gaussian 平滑。
iterations: 通过控制各层上迭代拟合次数控制跟踪精度。
polyN: 控制二次多项式拟合区间大小。
polySigma: polyN = 5, polySigma = 1.1; polyN = 7, polySigma = 1.5。
flags: 当使用 cv::OPTFLOW_USE_INITIAL_FLOW 时,flow 被同时当作输入参数,表示初始光流速度场;通常在序列视频中,相邻帧运动方向具有相似性,故可以使用上帧速度场作为初始猜测。
以下代码计算两帧图像间的速度场:
1 cv::Mat img0 = cv::imread("prev.bmp", cv::IMREAD_GRAYSCALE); 2 cv::Mat img1 = cv::imread("next.bmp", cv::IMREAD_GRAYSCALE); 3 cv::Mat flow(img0.size(), CV_32FC2); 4 cv::calcOpticalFlowFarneback(img0, 5 img1, 6 flow, 7 .5, 8 3, 9 5,10 1,11 7,12 1.5,13 cv::OPTFLOW_FARNEBACK_GAUSSIAN);14 15 cv::Mat flow2(flow.size(), CV_8UC1);16 for (int y = 0; y < flow.rows; ++y)17 {18 float* data1 = flow.ptr<float>(y);19 uchar* data2 = flow2.ptr<uchar>(y);20 for (int x = 0; x < flow.cols; ++x)21 {22 float mx = data1[x * 2];23 float my = data1[x * 2 + 1];24 float mv = sqrt(mx * mx + my * my);25 data2[x] = cv::saturate_cast<uchar>(mv * 10);26 }27 }28 cv::imwrite("Farneback.bmp", flow2);
执行效果如下:
参考资料: Learning Opencv 3   Adrian Kaehler & Gary Bradski
语言方法
2645zbuxr
F00go如何用抖音创意来进行变现
38992010.08.18 06-17-32
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
数字图像处理,相位相关算法解决图像的刚性平移问题
opencv学习笔记十四:使用cv2.findContours()和cv2.drawContours()实现轮廓检测
findContours()函数
光流(optical flow)和openCV中实现,opticalopencv
Gabor滤波器学习
python+opencv图像处理(二)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服