当前位置: 首页 > article >正文

OpenCV视觉分析之目标跟踪(1)计算密集光流的类DISOpticalFlow的介绍

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

这个类实现了 Dense Inverse Search (DIS) 光流算法。更多关于该算法的细节可以在文献 146中找到。该实现包含了三个预设参数集,以提供速度和质量之间的合理折衷。然而,即使是速度最慢的预设仍然相对较快,如果你需要更好的质量和不关心速度的话,可以使用 DeepFlow。

与论文中描述的算法相比,这个实现还包含了几个附加特性,包括光流向量的空间传播(通过 getUseSpatialPropagation 控制),以及利用传递给 calc 方法的初始光流近似值的选项(如果传递前一帧的光流场,这基本上就是时间传播)。

cv::DISOpticalFlow 是 OpenCV 中用于计算密集光流(Dense Optical Flow)的一种方法,它基于半相关(displaced-phase correlation)技术。该方法特别适用于实时应用,因为它提供了较高的精度并且计算效率较高。

主要特点

  • 实时性:适合实时应用,因为计算速度快。
  • 高精度:相较于传统的光流算法,如 Lucas-Kanade 或 Farneback 方法,DISOpticalFlow 提供了更高的精度。
  • 密集光流:能够计算图像中每个像素的光流向量,而不是稀疏点。

成员函数

函数create()

cv::DISOpticalFlow::create 是一个静态工厂方法,用于创建 DISOpticalFlow 类的实例。这个方法允许你在创建对象时指定预设参数,这些参数会影响算法的速度和质量。

原型
static Ptr<DISOpticalFlow> cv::DISOpticalFlow::create
(
	int 	preset = DISOpticalFlow::PRESET_FAST
)	
参数
  • 参数preset:这是一个可选参数,默认值为 DISOpticalFlow::PRESET_FAST。它指定了算法使用的预设配置。预设参数提供了速度和质量之间的不同权衡。

预设参数
DISOpticalFlow 类提供了几种预设参数,具体如下:

  • DISOpticalFlow::PRESET_ULTRAFAST:最快的预设,牺牲了一部分质量以获得最高的速度。
  • DISOpticalFlow::PRESET_FAST:较快的预设,默认值,提供了较好的速度和质量平衡。
  • DISOpticalFlow::PRESET_MEDIUM:中等速度的预设,进一步提高了质量。
  • DISOpticalFlow::PRESET_ULTRA:最慢的预设,提供了最高质量的结果。

函数getFinestScale()

v::DISOpticalFlow::getFinestScale() 是一个成员函数,用于获取当前 DISOpticalFlow 对象所使用的最精细尺度(finest scale)。尺度是指在计算光流时对输入图像进行金字塔分解的程度,尺度越大,图像分辨率越低;尺度越小,图像分辨率越高。

原型
virtual int cv::DISOpticalFlow::getFinestScale	(		)	const
返回值

返回一个整数,表示当前设置的最精细尺度。

作用

在光流计算中,尺度的选择对算法的精度和速度有很大影响。较高的尺度意味着较低的分辨率,这样可以提高计算速度,但可能降低精度;较低的尺度则相反,可以提高精度,但会增加计算量。

函数getGradientDescentIterations()

cv::DISOpticalFlow::getGradientDescentIterations() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在计算光流过程中执行梯度下降迭代的次数。这个参数对于算法的精度和性能有重要影响。

原型
virtual int cv::DISOpticalFlow::getGradientDescentIterations	(		)	const
返回值

返回一个整数,表示当前设置的梯度下降迭代次数。

作用

在光流计算过程中,梯度下降迭代次数决定了算法在每一步中优化光流场的次数。更多的迭代次数通常会导致更精确的光流估计,但也增加了计算时间。因此,在实际应用中需要在精度和速度之间做出权衡。

函数getPatchSize()

cv::DISOpticalFlow::getPatchSize() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在计算光流时所使用的补丁(patch)大小。补丁大小是指在光流计算过程中用来匹配像素块的窗口大小,它对算法的精度和计算效率有直接影响。

原型
virtual int cv::DISOpticalFlow::getPatchSize() const;
返回值

返回一个整数,表示当前设置的补丁大小。

作用

在光流计算过程中,补丁大小决定了用于匹配的像素块的尺寸。较大的补丁大小可能会提高匹配的鲁棒性和精度,但也会增加计算复杂度。较小的补丁大小则可以加快计算速度,但可能会降低精度。

函数getPatchStride()

cv::DISOpticalFlow::getPatchStride() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在计算光流时所使用的补丁(patch)步长。补丁步长决定了在计算光流的过程中,算法如何在图像上滑动补丁进行匹配。

原型
virtual int cv::DISOpticalFlow::getPatchStride	(		)	const
返回值

返回一个整数,表示当前设置的补丁步长。

作用

在光流计算过程中,补丁步长决定了补丁在图像上的移动距离。较大的步长可以减少计算的补丁数量,从而加快计算速度,但可能会导致精度下降。较小的步长则可以提高精度,但会增加计算量。

函数getUseMeanNormalization()

cv::DISOpticalFlow::getUseMeanNormalization() 是一个成员函数,用于查询当前 DISOpticalFlow 对象是否启用了均值归一化(mean normalization)。均值归一化是一种预处理技术,用于减小光照变化和其他环境因素对光流估计的影响。

原型
virtual bool cv::DISOpticalFlow::getUseMeanNormalization	(		)	const

返回值

返回一个布尔值,指示是否启用了均值归一化。

作用

均值归一化有助于提高光流估计的准确性,特别是在存在光照变化的情况下。通过均值归一化,算法会对图像中的每个补丁(patch)进行处理,使其均值接近于零,从而减少环境变化对光流估计的影响。

函数getUseSpatialPropagation()

cv::DISOpticalFlow::getUseSpatialPropagation() 是一个成员函数,用于查询当前 DISOpticalFlow 对象是否启用了空间传播(spatial propagation)。空间传播是一种后处理技术,用于改进光流估计的一致性和平滑性。

原型
virtual bool cv::DISOpticalFlow::getUseSpatialPropagation	(		)	const
返回值

返回一个布尔值,指示是否启用了空间传播。

作用

空间传播可以在光流估计之后,通过考虑周围像素的光流估计值来平滑和优化光流场。这有助于减少孤立的不一致估计,并且可以使最终的光流场更加一致和平滑。

函数getVariationalRefinementAlpha()

cv::DISOpticalFlow::getVariationalRefinementAlpha() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在变分细化(variational refinement)过程中使用的 alpha 参数值。这个参数影响着细化过程中的平滑程度。

原型
virtual float cv::DISOpticalFlow::getVariationalRefinementAlpha	(		)	const
返回值

返回一个浮点数,表示当前设置的 alpha 参数值。

作用

在光流计算过程中,变分细化是一种后处理步骤,用于提高光流场的质量。alpha 参数控制了细化过程中平滑项的权重。较大的 alpha 值会导致更平滑的光流场,而较小的 alpha 值则保留更多细节。

函数getVariationalRefinementDelta()

cv::DISOpticalFlow::getVariationalRefinementDelta() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在变分细化(variational refinement)过程中使用的 delta 参数值。这个参数影响着细化过程中的亮度一致性约束。

原型
virtual float cv::DISOpticalFlow::getVariationalRefinementDelta	(		)	const
返回值

返回一个浮点数,表示当前设置的 delta 参数值。

作用

在光流计算过程中,变分细化是一种后处理步骤,用于提高光流场的质量。delta 参数控制了亮度一致性约束的强度。较大的 delta 值意味着更高的容错性,即在亮度变化较大的情况下仍能保持较好的光流估计;较小的 delta 值则对亮度一致性要求更高,适用于亮度变化较小的情况。

函数getVariationalRefinementGamma()

cv::DISOpticalFlow::getVariationalRefinementGamma() 是一个成员函数,用于获取当前 DISOpticalFlow 对象在变分细化(variational refinement)过程中使用的 gamma 参数值。这个参数影响着细化过程中的平滑程度以及对噪声的敏感度。

原型

virtual float cv::DISOpticalFlow::getVariationalRefinementGamma	(		)	const

返回值

返回一个浮点数,表示当前设置的 gamma 参数值。

作用

在光流计算过程中,变分细化是一种后处理步骤,用于提高光流场的质量。gamma 参数控制了细化过程中对光流场平滑性和对噪声敏感性的平衡。较高的 gamma 值会使光流场更加平滑,但可能丢失一些细节;较低的 gamma 值则保留更多的细节,但也可能导致更多的噪声。

代码示例


#include <iostream>
#include <opencv2/opencv.hpp>

// 自定义函数,用于将光流向量转换为彩色图像
/// 自定义函数,用于将光流向量转换为彩色图像
void flowToColor(const cv::Mat& flow, cv::Mat& colorFlow) {
    const float maxMagnitude = 10.0f; // 可视化中的最大流速

    int cols = flow.cols;
    int rows = flow.rows;
    colorFlow.create(rows, cols, CV_8UC3);

    for (int y = 0; y < rows; ++y) {
        for (int x = 0; x < cols; ++x) {
            cv::Point2f fxy = flow.at<cv::Point2f>(y, x);
            float magnitude = std::sqrt(fxy.x * fxy.x + fxy.y * fxy.y);
            magnitude = std::min(magnitude / maxMagnitude, 1.0f); // 归一化

            // 使用HSV颜色空间来表示方向
            float angle = std::atan2(fxy.y, fxy.x);
            float hue = (angle + M_PI) / (2 * M_PI); // 转换为0-1范围内的Hue值
            hue = std::fmod(hue + 1.0f, 1.0f); // 确保Hue值在0-1之间

            // 构造HSV颜色
            cv::Vec3b hsv;
            hsv[0] = static_cast<uchar>(hue * 180); // Hue
            hsv[1] = static_cast<uchar>(magnitude * 255); // Saturation
            hsv[2] = static_cast<uchar>(255); // Value

            // 将HSV颜色转换为BGR颜色
            cv::Vec3b bgr;
            cv::Mat hsvPixel(1, 1, CV_8UC3, hsv);
            cv::Mat bgrPixel;
            cvtColor(hsvPixel, bgrPixel, cv::COLOR_HSV2BGR);
            bgr = bgrPixel.at<cv::Vec3b>(0, 0);

            // 设置颜色
            colorFlow.at<cv::Vec3b>(y, x) = bgr;
        }
    }
}
int main( int argc, char** argv )
{
    // 创建 DISOpticalFlow 对象
    cv::Ptr< cv::DISOpticalFlow > dis = cv::DISOpticalFlow::create();

    // 打开默认摄像头
    cv::VideoCapture cap( 0 );
    if ( !cap.isOpened() )
    {
        std::cout << "无法打开摄像头" << std::endl;
        return -1;
    }

    cv::Mat frame, prevFrame, gray, flow, colorFlow;

    // 读取第一帧作为初始帧
    cap >> frame;
    if ( frame.empty() )
    {
        std::cout << "结束读取" << std::endl;
        return -1;
    }

    cv::cvtColor( frame, prevFrame, cv::COLOR_BGR2GRAY );

    cv::namedWindow( "Optical Flow", cv::WINDOW_NORMAL );

    while ( true )
    {
        cap >> frame;  // 读取下一帧
        if ( frame.empty() )
        {
            std::cout << "结束读取" << std::endl;
            break;
        }

        cv::cvtColor( frame, gray, cv::COLOR_BGR2GRAY );

        // 计算光流
        dis->calc( prevFrame, gray, flow );

        // 将光流向量转换为彩色图像
        flowToColor( flow, colorFlow );

        // 更新前一帧
        prevFrame = gray.clone();

        // 显示光流图像
        cv::imshow( "Optical Flow", colorFlow );

        if ( cv::waitKey( 30 ) >= 0 )
        {
            break;
        }
    }

    return 0;
}

运行结果

在这里插入图片描述


http://www.kler.cn/news/366010.html

相关文章:

  • 边缘计算路由网关R40钡铼技术3LAN口1WAN口Modbus协议
  • TensorFlow面试整理-TensorFlow 数据处理
  • 在PHP中,读取大文件
  • 安全见闻---清风
  • 深入了解 kotlinx-datetime:配置与使用指南
  • vue写个表格,让它滚动起来,没有用datav,有的时候结合会出错,一种简单的方法,直接用animation
  • ffmpeg视频滤镜:定向模糊-dblur
  • 实战-任意文件下载
  • 爱奇艺大数据多 AZ 统一调度架构
  • Loess 局部权重回归
  • 构建中小企业设备管理平台:Spring Boot应用
  • 享元设计模式在Java坦克游戏中的应用
  • 深入详解 Java - Spring MVC
  • 15. 缓存(Cache)
  • 24-10-21-读书笔记(二十八)-《契诃夫文集》(十二)下([俄] 契诃夫 [译] 汝龙)我们会生活下去!
  • Island Architecture 孤岛架构
  • 正则表达式基本语法(快速认知)
  • 用xshell给服务器上传jar包
  • PVE系统无损挂载ntfs格式物理磁盘
  • 中小企业设备管理:Spring Boot实现指南
  • 2024-10-22 问AI: [AI面试题] 讨论递归神经网络 (RNN) 的概念
  • 枫清科技高雪峰:大模型要成为生产力才有生命力
  • Docker 镜像下载问题及解决办法
  • OpenCV单目相机内参标定C++
  • 深度剖析:电商 API 接口如何成就卓越用户体验
  • edge下默认pdf图标的修复办法