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

C++基于opencv的视频质量检测--图像清晰度检测

文章目录

    • 0.引言
    • 1. 原始算法实现
    • 2. 优化思路
    • 3. 优化后的代码
    • 4. 代码详细解读

0.引言

视频质量图像清晰度检测已在C++基于opencv4的视频质量检测中有所介绍,本文将详细介绍其优化版本。

1. 原始算法实现

原始代码:

double sharpnessDetect(const cv::Mat& srcImg) {
  const int kGaussianSize = 3;  // 高斯模糊的核大小

  cv::Mat grayImg;
  if (srcImg.channels() != 1) {
    cv::cvtColor(srcImg, grayImg, cv::COLOR_BGR2GRAY);
  } else {
    grayImg = srcImg;
  }

  cv::Mat blurredImg;
  cv::GaussianBlur(grayImg, blurredImg, cv::Size(kGaussianSize, kGaussianSize), 0);

  uint64_t sumFver = 0;
  uint64_t sumFhor = 0;
  uint64_t sumVver = 0;
  uint64_t sumVhor = 0;
  double blurFactor = 0.0;

  for (int r = 0; r < grayImg.rows; ++r) {
    for (int c = 0; c < grayImg.cols; ++c) {
      uint64_t diffFver = 0;
      uint64_t diffFhor = 0;
      uint64_t diffBver = 0;
      uint64_t diffBhor = 0;
      if (r != 0) {
        diffFver = static_cast<uint64_t>(std::abs(grayImg.at<uchar>(r, c) - grayImg.at<uchar>(r - 1, c)));
      }
      if (c != 0) {
        diffFhor = static_cast<uint64_t>(std::abs(grayImg.at<uchar>(r, c) - grayImg.at<uchar>(r, c - 1)));
      }
      if (r != 0) {
        diffBver = static_cast<uint64_t>(std::abs(blurredImg.at<uchar>(r, c) - blurredImg.at<uchar>(r - 1, c)));
      }
      if (c != 0) {
        diffBhor = static_cast<uint64_t>(std::abs(blurredImg.at<uchar>(r, c) - blurredImg.at<uchar>(r, c - 1)));
      }

      uint64_t verDiff = (diffFver > diffBver) ? (diffFver - diffBver) : 0;
      uint64_t horDiff = (diffFhor > diffBhor) ? (diffFhor - diffBhor) : 0;

      sumFver += diffFver;
      sumFhor += diffFhor;
      sumVver += verDiff;
      sumVhor += horDiff;
    }
  }

  double bFver = (static_cast<double>(sumFver - sumVver)) / (static_cast<double>(sumFver) + 1.0);
  double bFhor = (static_cast<double>(sumFhor - sumVhor)) / (static_cast<double>(sumFhor) + 1.0);
  blurFactor = (bFver > bFhor) ? bFver : bFhor;

  return 1.0 - blurFactor;
}

以下是原始代码的主要步骤:

  1. 图像预处理:将输入图像转换为灰度图。
  2. 高斯模糊:对灰度图像进行高斯模糊处理,得到模糊图像。
  3. 梯度计算:通过遍历每个像素,计算原始图像和模糊图像在垂直和水平方向上的梯度差异。
  4. 模糊因子计算:根据梯度差异,计算模糊因子,进而评估图像的清晰度。

存在的问题:

  • 效率低下:使用嵌套的for循环遍历每个像素,手动计算梯度,处理大尺寸图像时效率较低。

2. 优化思路

为了解决上述问题,我们对原始算法进行了以下优化:

  1. 向量化操作,避免显式循环:利用OpenCV的矩阵运算和函数,对整个图像进行批量处理,提高计算效率。
  2. 使用Sobel算子计算梯度:Sobel算子是常用的梯度计算方法,能够有效地提取图像的边缘信息。

3. 优化后的代码

以下是优化后的sharpnessDetect函数:

double sharpnessDetect(const cv::Mat& srcImg) {
    const int kGaussianSize = 3;  // 高斯模糊的核大小

    cv::Mat grayImg;
    if (srcImg.channels() != 1) {
        cv::cvtColor(srcImg, grayImg, cv::COLOR_BGR2GRAY);
    } else {
        grayImg = srcImg;
    }

    // 对灰度图像进行高斯模糊
    cv::Mat blurredImg;
    cv::GaussianBlur(grayImg, blurredImg, cv::Size(kGaussianSize, kGaussianSize), 0);

    // 计算原始图像和模糊图像的梯度
    cv::Mat gradXOrig, gradYOrig;
    cv::Mat gradXBlur, gradYBlur;

    cv::Sobel(grayImg, gradXOrig, CV_64F, 1, 0, 3);
    cv::Sobel(grayImg, gradYOrig, CV_64F, 0, 1, 3);

    cv::Sobel(blurredImg, gradXBlur, CV_64F, 1, 0, 3);
    cv::Sobel(blurredImg, gradYBlur, CV_64F, 0, 1, 3);

    // 计算梯度的绝对值
    cv::Mat absGradXOrig = cv::abs(gradXOrig);
    cv::Mat absGradYOrig = cv::abs(gradYOrig);

    cv::Mat absGradXBlur = cv::abs(gradXBlur);
    cv::Mat absGradYBlur = cv::abs(gradYBlur);

    // 计算梯度差的正值部分
    cv::Mat diffX = absGradXOrig - absGradXBlur;
    cv::Mat diffY = absGradYOrig - absGradYBlur;

    diffX = cv::max(diffX, 0);
    diffY = cv::max(diffY, 0);

    // 计算梯度的总和
    double sumFhor = cv::sum(absGradXOrig)[0];
    double sumFver = cv::sum(absGradYOrig)[0];

    // 计算梯度差的总和
    double sumVhor = cv::sum(diffX)[0];
    double sumVver = cv::sum(diffY)[0];

    // 计算模糊因子
    double bFver = (sumFver - sumVver) / (sumFver + 1e-6);
    double bFhor = (sumFhor - sumVhor) / (sumFhor + 1e-6);
    double blurFactor = std::max(bFver, bFhor);

    // 返回清晰度得分
    return 1.0 - blurFactor;
}

4. 代码详细解读

开始
图像是否为灰度图?
转换为灰度图
跳过转换
对灰度图像进行高斯模糊
计算原始图像和模糊图像的梯度
计算梯度的绝对值
计算梯度差的正值部分
计算梯度的总和
计算模糊因子
返回清晰度得分

流程说明:

  • 开始:函数sharpnessDetect开始执行。
  • 检查图像通道数:判断输入图像是否为灰度图。
    • 如果不是,转换为灰度图。
    • 如果是,跳过转换。
  • 高斯模糊:对灰度图像进行高斯模糊处理,得到模糊图像。
  • 计算梯度:使用Sobel算子计算原始图像和模糊图像在x和y方向的梯度。
  • 计算梯度的绝对值:对梯度矩阵取绝对值。
  • 计算梯度差的正值部分:计算原始梯度和模糊梯度之间的差异,保留正值部分。
  • 计算梯度的总和:分别计算原始梯度和差异梯度的总和。
  • 计算模糊因子:根据梯度总和计算模糊因子。
  • 返回结果:根据模糊因子计算清晰度得分,返回结果。

优化细节解读

  • 使用Sobel算子计算梯度cv::Sobel函数可以高效地计算图像在x和y方向的梯度,避免了手动计算相邻像素差异的繁琐过程。

  • 向量化操作:通过cv::abscv::sum等函数,对整个矩阵进行操作,充分利用了底层的优化和并行计算能力。

  • 梯度差的正值部分:使用cv::max函数,将梯度差中的负值置零,保留正值部分,与原始代码的逻辑一致。

  • 防止除零错误:在计算模糊因子时,分母加上了一个很小的值1e-6,防止除以零的情况。

  • 数据类型选择:使用CV_64F(双精度浮点型)确保计算的精度,避免数据溢出和精度损失。


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

相关文章:

  • rocketmq基本架构
  • 无人机在城市执法监管中的应用:技术革新与监管挑战
  • dp 凸优化
  • 免费!无水印下载!
  • Mixly米思齐1.0 2.0 3.0 软件windows版本MAC苹果电脑系统安装使用常见问题与解决
  • pikachu靶场-敏感信息泄露概述
  • electron 监听窗口高端变化
  • JS | CommonJS、AMD、CMD、ES6-Module、UMD五种JS模块化规范
  • 海外发稿:探索海外外媒宣发分发渠道-大舍传媒
  • 如何使用VBA识别Excel中的“单元格中的图片”(1/2)
  • 着色器的认识
  • JMeter之JMX文件解释
  • Windows驱动开发(三)—— 驱动和应用层通信的几种方式
  • Openpyxl--学习记录
  • 【文心智能体 | AI大师工坊】如何使用智能体插件,完成一款旅游类智能体的开发,来体验一下我的智能体『​​​​​​​背包客』
  • 如何将 Excel 数据转换为 SQL 脚本:基于 Java 的全面解析
  • 问:数据库SQL优化实践整理?
  • python 相关
  • Android--简易计算器实现
  • Redis中Lua脚本的使用场景
  • 深度学习领域如何正确地读取视频
  • java OOP 对象操作
  • 关于<a-upload-dragger>实现选择文件夹,上传文件夹中符合要求的文件,并在所有符合要求文件上传完成后统一进行提示。这里面文件是直接上传到七牛云
  • 利用ChatGPT完成2024年MathorCup大数据挑战赛-赛道A初赛:台风预测与分析
  • springMVC中的请求拦截器
  • 【杂谈】城市规划教育的危与机