C++基于opencv的视频质量检测--画面冻结检测

文章目录

    • 0.引言
    • [1. 原始代码分析](#1. 原始代码分析)
    • [2. 优化方案](#2. 优化方案)
    • [3. 优化后的代码](#3. 优化后的代码)
    • [4. 代码详细解读](#4. 代码详细解读)

0.引言

视频质量画面冻结检测已在C++基于opencv4的视频质量检测中有所介绍,本文将详细介绍其优化版本。

1. 原始代码分析

图像抖动检测的原始代码:

cpp 复制代码
bool ScreenFreezeDetection(const cv::Mat& srcImg) {
    if (srcImg.empty()) {
        return true;  // 直接返回true表示检测故障
    }

    cv::Mat backgroundA, backgroundB;

    // 1. 获取云台运动前的背景A
    static int frameCount = 0;
    if (frameCount < NUM_FRAMES) {
        if (frameCount == 0) {
            backgroundA = cv::Mat::zeros(srcImg.size(), srcImg.type());
        }
        cv::accumulate(srcImg, backgroundA);
        ++frameCount;

        if (frameCount == NUM_FRAMES) {
            backgroundA /= NUM_FRAMES;
        }
        return false;
    }

    // 2. 发送云台运动指令,改变场景

    // 3. 获取云台运动后的背景B
    if (frameCount < 2 * NUM_FRAMES) {
        int currentFrameIndex = frameCount - NUM_FRAMES;
        if (currentFrameIndex == 0) {
            backgroundB = cv::Mat::zeros(srcImg.size(), srcImg.type());
        }
        cv::accumulate(srcImg, backgroundB);
        ++frameCount;

        if (frameCount == 2 * NUM_FRAMES) {
            backgroundB /= NUM_FRAMES;
        }
        return false;
    }

    // 4. 计算背景A和背景B的颜色直方图
    cv::Mat histA, histB;
    int histSize = 256;
    float range[] = {0, 256};
    const float* histRange = {range};
    cv::calcHist(&backgroundA, 1, 0, cv::Mat(), histA, 1, &histSize, &histRange, true, false);
    cv::calcHist(&backgroundB, 1, 0, cv::Mat(), histB, 1, &histSize, &histRange, true, false);

    // 5. 计算直方图的相似度(使用相关性比较方法)
    double histSimilarity = cv::compareHist(histA, histB, cv::HISTCMP_CORREL);

    // 6. 判断相似度是否小于阈值,如果小于则认为画面冻结
    if (histSimilarity > HIST_SIM_THRESHOLD) {
        return true;
    } else {
        return false;
    }
}

存在的问题:

  1. 依赖外部设备运动:该算法需要通过控制云台运动来改变摄像机的视角,以获取不同的背景。这在实际应用中可能不方便,增加了系统的复杂性和成本。

  2. 复杂的背景处理:使用了帧累积和直方图比较的方法,计算量较大,效率较低。

  3. 静态场景误判:对于本身就没有明显变化的静态场景,可能误判为画面冻结。

2. 优化方案

  • 取消对云台运动的依赖:改为直接比较连续帧之间的相似度,避免对外部设备的依赖。

  • 使用结构相似度(SSIM):SSIM是一种衡量两幅图像相似度的指标,考虑了亮度、对比度和结构信息,比简单的直方图比较更准确。

  • 引入冻结帧计数:只有当连续多帧都满足冻结条件时,才认为画面冻结,减少了误报率。

  • 简化代码结构:移除了累积帧和直方图计算的复杂操作。

3. 优化后的代码

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/quality.hpp>  // 需要OpenCV Contrib模块

/**
 * @brief 检测画面冻结的函数
 * @param[in] srcImg 输入的当前图像帧
 * @return 如果检测到画面冻结返回true,否则返回false
 */
bool ScreenFreezeDetection(const cv::Mat& srcImg) {
    static cv::Mat prevImg;
    static int freezeFrameCount = 0;
    const int FREEZE_THRESHOLD = 30;  // 冻结帧计数阈值
    const double SIMILARITY_THRESHOLD = 0.99;  // 相似度阈值

    if (srcImg.empty()) {
        return true;  // 输入图像为空,认为画面冻结
    }

    if (prevImg.empty()) {
        prevImg = srcImg.clone();
        return false;  // 第一帧,没有参考,无法判断
    }

    // 计算当前帧与上一帧的结构相似度(SSIM)
    double similarity = cv::quality::QualitySSIM::compute(srcImg, prevImg, cv::noArray())[0];

    if (similarity >= SIMILARITY_THRESHOLD) {
        // 如果相似度高于阈值,认为画面可能冻结
        freezeFrameCount++;
    } else {
        // 相似度低于阈值,认为画面正常
        freezeFrameCount = 0;
    }

    prevImg = srcImg.clone();

    // 如果连续的冻结帧数量超过阈值,认为画面冻结
    if (freezeFrameCount >= FREEZE_THRESHOLD) {
        return true;
    } else {
        return false;
    }
}

4. 代码详细解读

流程说明:

  • 开始 :函数ScreenFreezeDetection开始执行。

  • 检查输入图像是否为空 :如果为空,返回true,认为画面冻结。

  • 检查prevImg是否为空 :如果是第一帧,初始化prevImg,返回false。

  • 计算SSIM相似度 :使用当前帧和prevImg计算SSIM相似度。

  • 判断相似度是否超过阈值:如果相似度高,认为画面可能冻结,冻结帧计数器加1;否则,重置计数器。

  • 更新prevImg :将当前帧保存为prevImg,供下一次计算使用。

  • 检查冻结帧计数器是否超过阈值 :如果超过,返回true,认为画面冻结;否则,返回false。

代码说明:

  • 使用静态变量保存上一帧图像和冻结帧计数器 :prevImg保存上一帧,freezeFrameCount统计连续冻结帧的数量。

  • 计算SSIM相似度 :使用cv::quality::QualitySSIM::compute函数计算当前帧与上一帧的SSIM相似度。

  • 判断画面是否冻结 :如果相似度超过阈值SIMILARITY_THRESHOLD,则增加冻结帧计数;否则,重置计数。

  • 返回检测结果 :当冻结帧计数超过阈值FREEZE_THRESHOLD,认为画面冻结。

相关推荐
AC赳赳老秦4 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
无名猿4 小时前
C++ 查找算法:std::find 与容器成员 find 的性能差距
c++·性能优化·stl·标准库
程序猿编码5 小时前
工业视觉多任务方案:可编程梯度信息视觉框架,训练评估 + C++ 部署完整实战
开发语言·c++·视觉·推理引擎
youdexiang6 小时前
iOS版本语音转文字工具:音频识别原理
音视频
朝朝辞暮i6 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
SHARK_pssm7 小时前
【C++——类和对象(下)】
开发语言·c++·经验分享·笔记
汉克老师7 小时前
GESP2026年9月认证C++二级( 第一部分选择题(1~7题)精讲
c++·gesp·小学生·学c++编程
沫璃染墨8 小时前
《从零入门Linux系统篇(五十四):线程篇·七——互斥锁底层原理:从原子交换到线程竞争与锁实现》
linux·运维·服务器·开发语言·c++·驱动开发·系统架构
可乐ea9 小时前
GitHub Security Lab 开源 Fuzzing Taskflow:让 LLM 智能体自己跑完 C/C++ 模糊测试
jvm·c++·github·模糊测试·mcp·代码agent·智能体自动化
朝朝辞暮i10 小时前
C++ 第 13 课:值传递 —— 为什么函数里改了,外面却没变?
java·c++·算法