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

基于现代 C++17 的模块化视频质量诊断处理流程设计

文章目录

    • 0. 引言
    • 1. 原始设计分析
    • 2. 新的设计思路
      • 2.1 定义通用的检测接口
      • 2.2 使用 `std::function` 和 `std::any` 管理检测模块
      • 2.3 构建可动态配置的检测管道
    • 3. 示例实现
      • 3.1 定义检测接口和模块
        • 3.1.1 检测接口
        • 3.1.2 信号检测模块
        • 3.1.3 冻结检测模块
        • 3.1.4 其他检测模块
      • 3.2 构建检测管道
        • 3.2.1 初始化管道
        • 3.2.2 创建检测模块实例
        • 3.2.3 将检测模块添加到管道
      • 3.3 执行检测管道
      • 3.4 完整代码示例
    • 4. 设计优势
      • 4.1 灵活性和可扩展性
      • 4.2 模块化和可维护性
      • 4.3 利用现代 C++ 特性
  • 5. 参考资料

0. 引言

在整理视频质量诊断程序模块代码时发现,处理流程通常是固定的,各种检测功能以函数形式顺序调用。这种设计缺乏灵活性,不易于扩展和维护。本文将使用 C++17 的 std::functionstd::any,重新设计视频质量诊断处理流程,实现模块化、可灵活扩展的处理管道。

视频质量诊断涉及多个检测模块,如信号检测、冻结检测、遮挡检测等。
详细见:

  • C++基于opencv4的视频质量检测
  • C++基于opencv的视频质量检测–图像清晰度检测
  • C++基于opencv的视频质量检测–画面冻结检测
  • C++基于opencv的视频质量检测–图像抖动检测
  • C++基于opencv的视频质量检测–遮挡检测

本文将采用面向接口的设计,使用现代 C++ 特性构建一个可动态配置的处理管道。

1. 原始设计分析

原始代码中,各个检测功能以独立的函数实现,处理流程固定:

signalDetect();
freezeframeDetect();
occlusionDetect();
brightnessDetect();
snownoiseDetect();
stripeDetect();
cameramoveDetect();
sharpnessDetect();
colorDetect();
jitterDetect();

这种设计存在以下问题:

  • 缺乏灵活性:处理流程固定,无法根据需求动态调整检测模块的顺序或添加新的检测功能。
  • 可扩展性差:添加新的检测功能需要修改主流程代码,增加了维护成本。
  • 模块耦合度高:各个检测函数之间可能存在隐式依赖,不利于模块化管理。

2. 新的设计思路

流程图

开始
初始化阈值和标志位
构建检测管道
遍历检测管道
执行检测模块
结束

2.1 定义通用的检测接口

借鉴 COM 的接口设计思想,定义一个通用的检测接口 IVideoQualityDetector

class IVideoQualityDetector {
public:
    virtual int Detect(const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                       const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                       DetectData_t* detectData) = 0;
    virtual ~IVideoQualityDetector() = default;
};

每个具体的检测模块都实现该接口,实现其特定的检测逻辑。

2.2 使用 std::functionstd::any 管理检测模块

  • std::function:用于存储各个检测模块的调用方法,便于在管道中按顺序执行。
  • std::any:用于存储不同类型的检测模块实例,实现类型擦除,支持在运行时动态管理模块。

2.3 构建可动态配置的检测管道

将各个检测模块实例化后,添加到一个检测管道(如 std::vector<std::function<int(...)>>)中。这样可以根据需求动态调整检测模块的顺序、添加或移除检测模块。

3. 示例实现

3.1 定义检测接口和模块

3.1.1 检测接口
class IVideoQualityDetector {
public:
    virtual int Detect(const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                       const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                       DetectData_t* detectData) = 0;
    virtual ~IVideoQualityDetector() = default;
};
3.1.2 信号检测模块
class SignalDetector : public IVideoQualityDetector {
public:
    int Detect(const cv::Mat& img, const cv::Mat&, const cv::Mat&,
               const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
               DetectData_t* detectData) override {
        // 实现信号检测逻辑
        if (img.empty()) return NO_DETECT;

        detectData->signalVal = signalDetect(img);
        if (detectData->signalVal >= threshold.signalThreshold) {
            detectDescribe->nosignalDescribe = NO_SIGNAL;
            return SIGNAL_DETECT;
        } else {
            detectDescribe->nosignalDescribe = SIGNAL_NORMAL;
        }
        return NO_DETECT;
    }
};
3.1.3 冻结检测模块
class FreezeFrameDetector : public IVideoQualityDetector {
public:
    int Detect(const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat&,
               const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
               DetectData_t* detectData) override {
        // 实现冻结检测逻辑
        if (img.empty() || img_jitterRef.empty()) return NO_DETECT;

        detectData->freezeFrameVal = 1 - freezeFrameDetect(img, img_jitterRef);
        if (detectData->freezeFrameVal >= threshold.freezeFrameThreshold) {
            detectDescribe->freezeFrameDescribe = FREEZEFRAME_YES;
            return FREEZEFRAME_DETECT;
        } else {
            detectDescribe->freezeFrameDescribe = FREEZEFRAME_NO;
        }
        return NO_DETECT;
    }
};
3.1.4 其他检测模块

按照上述方式,实现其他检测模块(遮挡检测、亮度检测、雪花噪点检测等),每个模块继承 IVideoQualityDetector 接口,实现其特定的 Detect 方法。

3.2 构建检测管道

3.2.1 初始化管道
std::vector<std::function<int(const cv::Mat&, const cv::Mat&, const cv::Mat&,
                              const Threshold_t&, DetectDescribe_t*, DetectData_t*)>> detectPipeline;
3.2.2 创建检测模块实例
std::any signalDetector = std::make_unique<SignalDetector>();
std::any freezeFrameDetector = std::make_unique<FreezeFrameDetector>();
// ... 创建其他检测模块实例
3.2.3 将检测模块添加到管道
detectPipeline.push_back([&](const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                             const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                             DetectData_t* detectData) {
    return std::any_cast<SignalDetector&>(signalDetector).Detect(img, img_jitterRef, img_moveRef,
                                                                 threshold, detectDescribe, detectData);
});

detectPipeline.push_back([&](const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                             const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                             DetectData_t* detectData) {
    return std::any_cast<FreezeFrameDetector&>(freezeFrameDetector).Detect(img, img_jitterRef, img_moveRef,
                                                                           threshold, detectDescribe, detectData);
});
// ... 将其他检测模块添加到管道

3.3 执行检测管道

for (auto& detectFunc : detectPipeline) {
    detectFunc(img, img_jitterRef, img_moveRef, threshold, detectDescribe, detectData);
}

3.4 完整代码示例

这里仅展示主要结构,完整代码应包括所有检测模块的实现。

#include <iostream>
#include <vector>
#include <functional>
#include <any>
#include <opencv2/opencv.hpp>

// 定义相关的常量、结构体和函数(如 Threshold_t、DetectDescribe_t、DetectData_t、signalDetect 等)

class IVideoQualityDetector {
public:
    virtual int Detect(const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                       const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                       DetectData_t* detectData) = 0;
    virtual ~IVideoQualityDetector() = default;
};

class SignalDetector : public IVideoQualityDetector {
public:
    int Detect(const cv::Mat& img, const cv::Mat&, const cv::Mat&,
               const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
               DetectData_t* detectData) override {
        // 信号检测实现
    }
};

// ... 实现其他检测模块

int ROCK_QualityDiagnoseFromMat(const cv::Mat img, cv::Mat img_jitterRef, cv::Mat img_moveRef,
                                Threshold_t threshold, DetectDescribe_t* detectDescribe,
                                DetectData_t* detectData, unsigned int flag) {
    // 初始化阈值和标志位
    init_threshold(threshold);
    init_flag(flag);

    // 构建检测管道
    std::vector<std::function<int(const cv::Mat&, const cv::Mat&, const cv::Mat&,
                                  const Threshold_t&, DetectDescribe_t*, DetectData_t*)>> detectPipeline;

    std::any signalDetector = std::make_unique<SignalDetector>();
    // ... 创建其他检测模块实例

    // 根据标志位添加需要的检测模块
    if (flag & SIGNAL_DETECT) {
        detectPipeline.push_back([&](const cv::Mat& img, const cv::Mat& img_jitterRef, const cv::Mat& img_moveRef,
                                     const Threshold_t& threshold, DetectDescribe_t* detectDescribe,
                                     DetectData_t* detectData) {
            return std::any_cast<SignalDetector&>(signalDetector).Detect(img, img_jitterRef, img_moveRef,
                                                                         threshold, detectDescribe, detectData);
        });
    }

    // ... 根据其他标志位添加检测模块

    // 执行检测管道
    for (auto& detectFunc : detectPipeline) {
        detectFunc(img, img_jitterRef, img_moveRef, threshold, detectDescribe, detectData);
    }

    return 0;
}

4. 设计优势

4.1 灵活性和可扩展性

  • 动态配置检测模块:可以根据需要在运行时添加、移除或重新排列检测模块,无需修改主流程代码。
  • 支持新功能的扩展:添加新检测功能只需实现 IVideoQualityDetector 接口,并在构建管道时添加即可。

4.2 模块化和可维护性

  • 降低模块耦合度:各个检测模块独立实现,遵循统一的接口,模块之间无直接依赖。
  • 易于维护和测试:每个检测模块可以独立开发和测试,提高代码质量。

4.3 利用现代 C++ 特性

  • std::function:方便地管理和调用函数对象,实现检测管道的灵活组织。
  • std::any:实现类型擦除,支持在运行时管理不同类型的检测模块实例。

5. 参考资料

  • C++17 std::function 文档
  • C++17 std::any 文档
  • OpenCV 官方文档

http://www.kler.cn/a/370673.html

相关文章:

  • java使用poi-tl自定义word模板导出
  • LabVIEW串口通信调试与数据接收问题
  • 【MySQL】复合查询+表的内外连接
  • 无降智o1 pro——一次特别的ChatGPT专业模式探索
  • LARGE LANGUAGE MODELS ARE HUMAN-LEVEL PROMPT ENGINEERS
  • 如何保证光谱相机的稳定性和可靠性
  • Python入门:学会Python装饰器让你的代码如虎添翼!(Python如何不改动原有函数代码添加一些额外的功能)
  • 嵌入式linux系统中实现MPU6050的控制方法
  • Python OpenCV图像复原
  • HCIP 路由控制
  • GRE VPN(H3C)
  • node.js学习Day2
  • asp.net WebForm GridView高级应用
  • 精选免费剪辑软件,为你的视频创作添彩
  • 排序(一)插入排序,希尔排序,选择排序,堆排序,冒泡排序
  • Redis Bitmap介绍和使用场景
  • 《链表篇》---环形链表II(返回节点)
  • Pytorch笔记--RuntimeError: NCCL communicator was aborted on rank 3.
  • C#自定义事件的案例
  • 前端阻止用户调试(禁用F12,禁用右键菜单,禁用查看源代码,禁用复制,无限debugger断点)
  • 【Linux 从基础到进阶】高负载系统的优化与维护
  • Java学习Day51:紫云山金丹培育基地(移动端开发之多表联查,发送短信验证码)
  • Spring Task—定时任务
  • 钉钉日常报销单与金蝶云星空集成技术详解
  • springboot配置websocket
  • 2025秋招八股文--RPC篇