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

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(双精度浮点型)确保计算的精度,避免数据溢出和精度损失。

相关文章:

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

文章目录 0.引言1. 原始算法实现2. 优化思路3. 优化后的代码4. 代码详细解读 0.引言 视频质量图像清晰度检测已在C基于opencv4的视频质量检测中有所介绍&#xff0c;本文将详细介绍其优化版本。 1. 原始算法实现 原始代码&#xff1a; double sharpnessDetect(const cv::Ma…...

力扣11.1

2518. 好分区的数目 给你一个正整数数组 nums 和一个整数 k 。 分区 的定义是&#xff1a;将数组划分成两个有序的 组 &#xff0c;并满足每个元素 恰好 存在于 某一个 组中。如果分区中每个组的元素和都大于等于 k &#xff0c;则认为分区是一个好分区。 返回 不同 的好分区…...

打印室预约系统|基于java和小程序的打印室预约系统设计与实现(源码+数据库+文档)

打印室预约系统 目录 基于java和小程序的打印室预约系统设计与实现 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#x…...

操作系统-多线程案例

一、单例模式&#xff08;是一种设计模式&#xff09; 设计模式有很多种&#xff0c;不同的语法中也有不同的设计模式 单例 单个实例&#xff08;对象) 某个类&#xff0c;在一个进程中&#xff0c;只应该创建出一个实例&#xff0c;&#xff08;原则上不该有多个&#xff…...

什么是FUSE用户态文件系统

零. 文件系统 1. 为什么要有文件系统 文件系统是操作系统中管理文件和目录的一种机制。它提供了组织、存储、检索和更新文件的方法&#xff0c;主要如下&#xff1a; 数据组织&#xff1a;文件系统将数据组织成文件和目录&#xff0c;使用户能够更方便地管理和查找文件。每个…...

[每日一练]销售分析(通过数据的0/1转换进行是否存在的查询)

#该题目来源于力扣&#xff1a; 1083. 销售分析 II - 力扣&#xff08;LeetCode&#xff09; 题目要求&#xff1a; 表&#xff1a;Product----------------------- | Column Name | Type | ----------------------- | product_id | int | | product_name | varch…...

.NET Core WebApi第7讲:项目的发布与部署

一、理解 前端跟后端拿数据&#xff0c;然后在前端页面中展示&#xff0c;就是我们要完成的事情。 把前端跟后端开发好之后&#xff0c;我们需要落地部署&#xff0c;这个时候就需要一个服务器。 服务器就是一台电脑&#xff0c;只要windows里面有一个叫IIS的管理器。 二、项目…...

【python 将数据写入csv文件】正确方式

data [{username: jack, password: 1234}, ……]# 保存为CSV文件 with open(IP_output.csv, w, newline, encodingutf-8) as file:fieldnames [username, password]writer csv.DictWriter(file, fieldnamesfieldnames, quotingcsv.QUOTE_NONE)writer.writeheader() # 写入列…...

OpenCV4.8 开发实战系列专栏之 10 - 像素值统计

大家好,欢迎大家学习OpenCV4.8 开发实战专栏,长期更新,不断分享源码。 专栏代码全部基于C++ 与Python双语演示,专栏答疑群 请联系微信 OpenCVXueTang_Asst 本文关键知识点:像素值统计 最小(min)最大(max)均值(mean)标准方差(standard deviation)API知识点 最大最小值min…...

pandas计算相关性并画热力图

实现这个功能有很多方法&#xff0c;但是下面的方法还是比较优雅的&#xff1a; cols ["ASSET", "HOUSES", "INCOME", "DEBT", "EDUC"] corr df[cols].corr() corr.style.background_gradient(axisNone)讲解&#xff1a; …...

初始Docker

概述&#xff1a; 容器&#xff0c;作为云原生技术的重要组成部分&#xff0c;与虚拟机一样&#xff0c;均属于虚拟化技术的范畴。然而&#xff0c;容器技术以其独特的优势&#xff0c;在虚拟化领域中脱颖而出。与虚拟机不同&#xff0c;容器能够摆脱操作系统的束缚&#xff0…...

Redis-概念、安装、基本配置

文章目录 一、Redis及Redis集群概念、分布式系统概念一-1 Redis是什么一-2 什么是分布式系统、分布式缓存一-3 什么是Redis集群、实现Redis集群的方法有哪些、这些跟Redis的sentinel和cluster有什么关系一-4 Redis的库一-5 Redis中的Key与Value是什么、如何进行操作使用它们添加…...

qt QPlainTextEdit详解

QPlainTextEdit是一个功能强大、易于使用的纯文本编辑器/查看器。它使用与QTextEdit相同的技术和概念&#xff0c;但是为纯文本的处理进行了优化&#xff0c;因此更适合处理大型纯文本文档。QPlainTextEdit不提供富文本编辑功能&#xff0c;如字体、颜色、大小等的格式化&#…...

【机器学习】23. 聚类-GMM: Gaussian Mixture Model

1. 定义和假设 定义&#xff1a;probabilistic clustering&#xff08;model-base&#xff09; 假设&#xff1a;数据服从正态分布 2. 算法内容 我们假设数据是由k个高斯&#xff08;正态&#xff09;分布混合生成的。每个分布有2个参数&#xff1a;μ和σ。 一个分布对应一…...

深度探索C++对象模型

文章目录 前言一、关于对象C对象模型 二、构造函数实例分析 拷贝构造函数程序转化语意学(Program Transformation Semantics)成员初始化列表 三、数据语义学(The Semantics of Data)数据存取多种继承情况讨论仅单一继承加上虚函数多重继承虚拟继承 Pointer to Data Members 四、…...

电脑怎么设置开机密码:保障个人信息安全的第一步

在数字化时代&#xff0c;个人信息的安全至关重要。电脑作为我们日常工作和生活中不可或缺的设备&#xff0c;存储了大量的私人数据和敏感信息。为了防止未经授权的访问&#xff0c;设置开机密码是保护个人隐私和信息安全的基本措施之一。本文将详细介绍如何在不同操作系统下为…...

MybatisPlus入门(六)MybatisPlus-null值处理

一、MybatisPlus-null值处理 1.1&#xff09;问题引入&#xff1a; 在查询中遇到如下情况&#xff0c;有部分筛选条件没有值&#xff0c;如商品价格有最大值和最小值&#xff0c;商品价格部分时候没有值。 1.2&#xff09;解决办法&#xff1a; 步骤一&#xff1a;新建查询实…...

红帽认证有必要考吗?这四大人群推荐考取!

红帽认证(Red Hat Certification)作为全球公认的Linux技能认证&#xff0c;对于某些特定人群来说&#xff0c;考取这一认证无疑是一个明智的选择。本文将探讨红帽认证的必要性&#xff0c;并为四类人群提供考取红帽认证的建议。 1. IT专业人士 对于IT专业人士来说&#xff0…...

基于SSM+微信小程序的社团登录管理系统(社团1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 2、项目技术 3、开发环境 4、功能介绍 1、项目介绍 基于SSM微信小程序的社团登录管理系统实现了管理员及社团、用户。 1、管理员实现了首页、用户管理、社团管理、社团信息管理、社…...

html中cookie如何存储

在HTML中&#xff0c;可以使用JavaScript来创建、读取和删除cookie。以下是创建和读取cookie的基本示例&#xff1a; 创建cookie: function setCookie(name, value, daysToLive) { var cookie name "" encodeURIComponent(value); if (typeof daysToLive …...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...