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

基于现代 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 官方文档

相关文章:

基于现代 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 构建检…...

高级java每日一道面试题-2024年10月23日-JVM篇-说一下JVM有哪些垃圾回收算法?

如果有遗漏,评论区告诉我进行补充 面试官: 说一下JVM有哪些垃圾回收算法? 我回答: 在 Java 虚拟机 (JVM) 中&#xff0c;垃圾回收 (Garbage Collection, GC) 是一项非常重要的功能&#xff0c;用于自动管理应用程序的内存。JVM 采用多种垃圾回收算法来决定何时以及如何回收…...

高效文本编辑与导航:Vim中的三种基本模式及粘滞位的深度解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…...

w005基于Springboot学生心理咨询评估系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…...

实战-任意文件下载

实战-任意文件下载 1、开局 开局一个弱口令&#xff0c;正常来讲我们一般是弱口令或者sql&#xff0c;或者未授权 那么这次运气比较好&#xff0c;直接弱口令进去了 直接访问看看有没有功能点&#xff0c;正常做测试我们一定要先找功能点 发现一个文件上传点&#xff0c;不…...

PG数据库之视图详解

1. 视图的基本定义 在PostgreSQL&#xff08;简称pg&#xff09;数据库中&#xff0c;视图&#xff08;View&#xff09;是一种虚拟表&#xff0c;其内容由SQL查询定义。视图并不实际存储数据&#xff0c;而是在每次查询时根据定义的查询语句动态生成结果。视图可以简化复杂的…...

时间序列预测(十五)——有关Python项目框架的实例分析

#1024程序员节&#xff5c;征文# 在之前的学习中&#xff0c;已经对时间序列预测的相关内容有了大致的了解。为了进一步加深理解&#xff0c;并能够将所学知识应用于实际中&#xff0c;我决定找一个完整的Python框架来进行深入学习。经过寻找&#xff0c;我终于找到了一篇非常具…...

ETL、ELT和反向ETL都有什么不同?怎么选择?

数据处理是现代企业中不可或缺的一部分。随着数据量的不断增长&#xff0c;如何高效地处理、转换和加载数据变得尤为重要。本文将介绍三种常见的数据处理方式&#xff1a;ETL、ELT和反向ETL&#xff0c;帮助读者更好地理解和选择适合自己业务需求的方式。 一、ETL 定义&#…...

linux 中文实用型手册 基于RHEL(红帽系)

硬件系统 Updated by wangjing on 2024-10-28 at 02:36:57 in Tongzhou District, Beijing. 硬件信息 机器型号 dmidecode | grep "Product Name"CPU型号 cat /proc/cpuinfo |grep "model name" | uniqWWWCPU详情 lscpuCPU个数 cat /proc/cpuinfo |grep &q…...

Hash表算法

哈希表 理论知识&#xff08;本文来自于代码随想录摘抄&#xff09;什么是哈希常见的三种哈希结数组&#xff1a;set:map:其他常用方法或者技巧&#xff08;自己总结的&#xff09; 练习题和讲解有效的字母移位词349. 两个数组的交集1. 两数之和454. 四数相加 II15. 三数之和 总…...

MySQL企业常见架构与调优经验分享

文章目录 一、选择 PerconaServer、MariaDB 还是 MYSQL二、常用的 MYSQL 调优策略三、MYSOL 常见的应用架构分享四、MYSOL 经典应用架构 观看学习课程的笔记&#xff0c;分享于此~ 课程&#xff1a;MySQL企业常见架构与调优经验分享 mysql官方优化文档 调优MySQL参数 一、选择 …...

C++引用类型变量

引用变量的主要用途是用作函数的形参。这样函数将使用原始数据&#xff0c;而不是副本。除指针之外&#xff0c;引用也为处理大型结构提供了一种非常方便的途径。 再C中使用&符号标识引用。也就是说C给&符号赋予了另一个含义&#xff0c;将其用来声明引用。 引用的声…...

《C++23 新特性:现代软件开发的变革力量》

在软件开发的快速演进中&#xff0c;C作为一种强大且广泛应用的编程语言&#xff0c;不断推陈出新以适应日益复杂的开发需求。C23 的到来&#xff0c;为现代软件开发带来了诸多新的机遇和挑战。它的新特性不仅影响着开发者的编程习惯&#xff0c;也在代码效率、可维护性以及软件…...

Educational Codeforces Round 88 E. Modular Stability

题目链接 Educational Codeforces Round 88 E. Modular Stability 思路 对于任意的非负整数 x x x&#xff0c;我们要满足 x % a % b x % b % a x \% a \% b x \% b \% a x%a%bx%b%a。因为 a < b a < b a<b&#xff0c;所以只有 b b b为 a a a的倍数时才满足条件…...

Android中SurfaceView与GLSurfaceView 的关系

SurfaceView 与 GLSurfaceView 的关系 在 Android 开发中&#xff0c;SurfaceView 和 GLSurfaceView 是实现自定义渲染效果的关键组件。它们提供了不同的渲染方式&#xff0c;适用于不同的应用场景。我们将通过以下几个方面详细说明 SurfaceView 和 GLSurfaceView 的特点及实现…...

numpy——数学运算

一、标量——矢量 import numpy as npa 3.14 b np.array([[9, 5], [2, 7]])print(a) print(b)# ---------- 四则运算 ---------- print(a b) # np.add print(a - b) # np.subtract print(a * b) # np.multiply print(a / b) # np.divide 二、矢量——矢量 import nump…...

【工具】Charles对360浏览器抓包抓包

Charles 和 switchy sharp 配合&#xff0c;可以对 Chrome 进行抓包也可以配合对360安全浏览器抓包。 本文以Windows 电脑中的配置为例&#xff0c;介绍如何实现抓包。&#xff08;Mac中操作基本一致&#xff09; 1.安装Charles 可根据自己的电脑下载对应的版本&#xff1a;…...

【HarmonyOS】判断应用是否已安装

【HarmonyOS】判断应用是否已安装 前言 在鸿蒙中判断应用是否已安全&#xff0c;只是通过包名是无法判断应用安装与否。在鸿蒙里新增了一种判断应用安装的工具方法&#xff0c;即&#xff1a;canOpenLink。 使用该工具函数的前提是&#xff0c;本应用配置了查询标签querySch…...

Qt Designer客户端安装和插件集(pyqt5和pyside2)

GitHub - PyQt5/QtDesignerPlugins: Qt Designer PluginsQt Designer Plugins. Contribute to PyQt5/QtDesignerPlugins development by creating an account on GitHub.https://github.com/PyQt5/QtDesignerPlugins 一、下载客户端 https://github.com/PyQt5/QtDesigner/rel…...

基于边缘计算的智能门禁系统架构设计分析

案例 阅读以下关于 Web 系统架构设计的叙述&#xff0c;回答问题1至问题3。 【说明】 某公司拟开发一套基于边缘计算的智能门禁系统&#xff0c;用于如园区、新零售、工业现场等存在来访被访业务的场景。来访者在来访前&#xff0c;可以通过线上提前预约的方式将自己的个人信息…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

Mysql故障排插与环境优化

前置知识点 最上层是一些客户端和连接服务&#xff0c;包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念&#xff0c;为通过安全认证接入的客户端提供线程。同样在该层上可…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

云原生安全实战:API网关Envoy的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口&#xff0c;负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...