📜  OpenCV – Gunnar-Farneback 光流(1)

📅  最后修改于: 2023-12-03 14:44:54.183000             🧑  作者: Mango

OpenCV – Gunnar-Farneback 光流

1. 简介

光流是计算机视觉中的一项基本技术,用于估计相邻帧之间物体的运动。Gunnar Farneback 是瑞典卡罗林斯卡医学院的教授,他的光流算法被广泛应用于计算机视觉领域。

OpenCV 提供了基于 Gunnar-Farneback 光流的函数,可以用于实现光流场的计算。该算法通过估计像素间的偏移量来计算光流场。

2. 使用方法
cv::calcOpticalFlowFarneback(prevImg, nextImg, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags);

该函数接受以下参数:

  • prevImg:前一张图像
  • nextImg:后一张图像
  • flow:输出的光流场
  • pyr_scale:图像金字塔缩放比例
  • levels:图像金字塔层数
  • winsize:窗口大小
  • iterations:迭代次数
  • poly_n:多项式展开的阶数
  • poly_sigma:多项式展开的标准差
  • flags:算法标志
3. 示例代码
#include <opencv2/opencv.hpp>

using namespace cv;

int main()
{
    Mat prevImg, nextImg;
    // 读取前一张图像和后一张图像
    prevImg = imread("prev.jpg", IMREAD_GRAYSCALE);
    nextImg = imread("next.jpg", IMREAD_GRAYSCALE);
    if (prevImg.empty() || nextImg.empty())
    {
        std::cout << "Failed to load images!" << std::endl;
        return -1;
    }
    Mat flow;
    // 计算光流场
    calcOpticalFlowFarneback(prevImg, nextImg, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
    // 可视化光流场
    Mat flowImg;
    cvtColor(prevImg, flowImg, COLOR_GRAY2BGR);
    for (int y = 0; y < flowImg.rows; y += 5)
    {
        for (int x = 0; x < flowImg.cols; x += 5)
        {
            // 读取像素点处的光流向量
            const Point2f& fxy = flow.at<Point2f>(y, x);
            // 绘制光流向量
            line(flowImg, Point(x, y), Point(cvRound(x+fxy.x), cvRound(y+fxy.y)), Scalar(0,255,0));
        }
    }
    imshow("prev", prevImg);
    imshow("next", nextImg);
    imshow("flow", flowImg);
    waitKey();
    return 0;
}

以上代码读取了两张图像,然后计算两张图像之间的光流场,并可视化出来。可视化的结果如下图所示:

optical_flow

4. 总结

通过本篇文章的介绍,我们了解了 OpenCV 中的 Gunnar-Farneback 光流算法,并且学习了如何使用该算法计算光流场。在实践中,我们可以将该算法应用于目标跟踪、运动分析等领域,以实现更好的计算机视觉效果。