python的opencv操作记录(九)——图像清晰度计算

news2025/7/7 17:22:28

文章目录

  • 图像清晰度计算的一般思路
    • 图像梯度
    • 图像梯度绝对值与梯度角度
  • 基于梯度的方式
      • 计算梯度算子1——Sobel算子
      • 计算梯度算子2——Laplacian算子
    • 梯度统计评分
      • 平均梯度
      • 梯度总和
  • Demo

图像清晰度计算的一般思路

定义图像清晰度是一个比较定制化,或者说比较偏业务属性的,就是说要根据需要来定义图像的清晰度。
但是一般来说,还是有个一般过程。

  • 一般来说,清晰的图像的另外一个含义就是轮廓清晰,物体之间的边缘明显。从图像频域的角度来看,就是图像的高频分量较多。
  • 通过图像求导的来得到图像的梯度,梯度越大,说明像素变化越大,物体之间的边缘也就越清晰。

图像的频域之前的文章说过了,这里说一下图像的梯度问题。

图像梯度

图像梯度的定义分为两个维度:

  • X方向上的梯度:当前像素右侧的像素值减去当前像素左侧像素的像素值
  • Y方向上的梯度:当前像素下方的像素值减去当前像素上方像素的像素值

用一个向量来表示的话就是:
∇ f ( x , y ) = [ g x g y ] = [ f ( x + 1 , y ) − f ( x − 1 , y ) f ( x , y + 1 ) − f ( x , y − 1 ) ] \nabla f(x,y) = \begin{bmatrix} g_x \\ g_y \end{bmatrix} = \begin{bmatrix} f(x+1, y) - f(x-1, y) \\ f(x, y+1) - f(x, y-1) \end{bmatrix} f(x,y)=[gxgy]=[f(x+1,y)f(x1,y)f(x,y+1)f(x,y1)]

在图像计算领域中,最经典的计算方式就是掩码方式,或者说是卷积的方式。
上面一个公式在图像领域就可以用一个掩码来表示:

  • X方向的掩码:
    [ − 1 , 0 , 1 ] \begin{bmatrix} -1, 0, 1 \end{bmatrix} [1,0,1]
  • Y方向的掩码:
    [ − 1 , 0 , 1 ] \begin{bmatrix} -1, \\ 0, \\ 1 \end{bmatrix} 1,0,1

图像梯度绝对值与梯度角度

如果减出来的数字小于0,是没有意义的,所以有一个梯度绝对值的计算方法:
g x 2 + g y 2 \sqrt{g_x^2 + g_y^2} gx2+gy2

梯度角度定义为:
a r c t a n ( g x g y ) arctan(\frac{g_x}{g_y}) arctan(gygx)

基于梯度的方式

基于梯度的计算方式一般分成两步:

  • 计算梯度
  • 针对梯度进行统计评分

计算梯度算子1——Sobel算子

Sobel算子的一般过程:

  • 利用下面的两个掩码对图像进行计算,一个是X方向上的,一个是Y方向上的:

    • X方向上的掩码
      [ − 1 0 1 − 2 0 2 − 1 0 1 ] \begin{bmatrix} -1 & 0 & 1\\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} 121000121

      g ( x ) = − f ( x − 1 , y − 1 ) + f ( x + 1 , y − 1 ) − 2 f ( x − 1 , y ) + 2 f ( x + 1 , y ) − f ( x − 1 , y + 1 ) + f ( x + 1 , y + 1 ) g(x) = -f(x-1, y-1) + f(x+1, y-1) -2f(x-1,y) \\+2f(x+1, y) - f(x-1, y+1) + f(x+1,y+1) g(x)=f(x1,y1)+f(x+1,y1)2f(x1,y)+2f(x+1,y)f(x1,y+1)+f(x+1,y+1)

    • Y方向上的掩码
      [ − 1 − 2 − 1 0 0 0 1 2 1 ] \begin{bmatrix} -1 & -2 & -1\\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix} 101202101

      g ( y ) = − f ( x − 1 , y − 1 ) − 2 f ( x + 1 , y − 1 ) − f ( x − 1 , y ) + 2 f ( x + 1 , y ) − f ( x − 1 , y + 1 ) + f ( x + 1 , y + 1 ) g(y) = -f(x-1, y-1) - 2f(x+1, y-1) -f(x-1,y) \\+2f(x+1, y) - f(x-1, y+1) + f(x+1,y+1) g(y)=f(x1,y1)2f(x+1,y1)f(x1,y)+2f(x+1,y)f(x1,y+1)+f(x+1,y+1)

直接通过掩膜计算就可以得到sobel算子计算后的图像。
我使用的是opencv,具体的可以参考官网的说明文档:
https://docs.opencv.org/4.6.0/d4/d86/group__imgproc__filter.html#gacea54f142e81b6758cb6f375ce782c8d

这里有一个问题,就是在求梯度的过程中,是个1 * 3或者3 * 1的向量,这里是一个矩阵,虽然看上去和上面的很类似,而且官网文档上有这么一句:
The Sobel operators combine Gaussian smoothing and differentiation,就是说综合和求梯度和高斯模糊两种操作。
我的理解如下:X和Y上的梯度就和第一部分描述的一样,就是按照梯度的定义来计算的,而 3 * 3矩阵中的中间部分[-2, 0, 2]加上两边的[-1, 0, 1]组成的矩阵是服从高斯分布的,参考:https://blog.csdn.net/Quincuntial/article/details/50625389。
而且在opencv的sobel算子中,这个矩阵还可以是5 * 5和7 * 7的,我的理解也是这个矩阵的各个数字在某种程度上是服从高斯分布的。
不知道正不正确,如果有哪位朋友清楚,请指教,谢谢。

计算梯度算子2——Laplacian算子

拉普拉斯算子和sobel很类似,实际上就是x方向上做两次sobel算子计算,然后在y方向上也做两次sobel算子计算,然后再把两者相加。
如果ksize=1的话,就使用一个特殊的掩膜进行计算,可以参考opencv官方文档:
https://docs.opencv.org/4.6.0/d4/d86/group__imgproc__filter.html#gad78703e4c8fe703d479c1860d76429e6

官网上写的是:
d s t = Δ s r c = ∇ 2 f ( x ) + ∇ 2 f ( y ) dst=\Delta src=\nabla ^2f(x) + \nabla ^2f(y) dst=Δsrc=2f(x)+2f(y)

梯度统计评分

得到梯度图像后,对整个梯度图像进行统计,一般来说可以用梯度平均值来代表原始图像的梯度分布:

平均梯度

调用cv2中的mean函数计算梯度:
score = cv2.mean(img_lap)

梯度总和

调用cv2中的sumElems函数计算梯度图中所有点之和
score = cv2.sumElems(img_lap)

Demo

我从网上找了两张图,一张是对焦不那么清楚的,一张是对焦相对比较清楚的,我们用上述的方式进行一个简单的实验:

模糊图
清晰图

代码如下:

img_blur = cv2.imread("/Users/zoulei/files/personal/images/1.jpg", 0)

img_blur_lap = cv2.Laplacian(img_blur, cv2.CV_8UC1, ksize=3)

score_blur = cv2.sumElems(img_blur_lap)

print(score_blur)

mean_value_blur_laplacian = cv2.mean(img_blur_lap)
print(mean_value_blur_laplacian)

img_clear = cv2.imread("/Users/zoulei/files/personal/images/2.jpg", 0)

img_clear_lap = cv2.Laplacian(img_clear, cv2.CV_8UC1, ksize=3)

score_clear = cv2.sumElems(img_clear_lap)

print(score_clear)

mean_value_clear_laplacian = cv2.mean(img_clear_lap)
print(mean_value_clear_laplacian)

输出结果:
score_blur:(411391.0, 0.0, 0.0, 0.0)
mean_value_blur_laplacian:(10.624767561983472, 0.0, 0.0, 0.0)
score_clear:(635569.0, 0.0, 0.0, 0.0)
mean_value_clear_laplacian:(16.11238148354713, 0.0, 0.0, 0.0)

从结果可以看出,通过拉普拉斯算子是可以计算出图像的清晰度来的。
当然,有一种情况,在光学相机拍摄的图像里面,有些是会突出前景而虚化背景的,这种情况下就需要先提取一下感兴趣区域之后再对感兴趣区域进行计算了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySql面试

0. InnoDB与MyISAM的区别 1)InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提 交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务&…

【Vue3+TS】Axios拦截器封装及跨域 [cors] 解决方案

【Vue3TS】Axios拦截器封装及跨域 [cors] 解决方案简述封装过程文件路径拦截器封装 —— Interceptor.tsAPI请求管理前端跨域的解决方案后端跨域的解决方案效果结语简述 我的项目采用 Vue3TypeScriptViteElement Plus 的组合,这个组合也是Vue版本退出3.x后官方推荐版…

记一次服务宕机、优化全流程(以后也可以装X了)

视频地址: https://www.bilibili.com/video/BV1924y1y7jN 221115上午10点的时候客户反应进入小程序慢,打开监控发现服务pv已经超过了历史之最(印象中最高的是100w),这次到了400w。原因是因为推广了一个发红包的活动。 …

Java练习题第二十七期:幸运的袋子

作者:有只小猪飞走啦 博客地址:文章目录前言一,题目二,解析三,代码前言 本博客是小博主在做Java算法题的过程中一些觉得可以分享的题目,希望对你们有帮助,如果哪里写错了或者有更好的解法&…

详解Unity中的Nav Mesh新特性|导航寻路系统 (一)

前言 之前我们讲解过Unity的Nav Mesh系统,其中提到过这个新版的Nav Mesh,它解决现有Nav Mesh的几个缺陷,比如无法动态烘焙,无法按照Agent的半径和高度适当的判断可行路径。现在新版Nav Mesh可以彻底解决这个问题!某种…

实验送样、数据分析样品、组名命名规范

俗话说巧妇难为无米之炊,而样品就是“米”,没有样品,就无法开展实验,无法获得数据,无法毕业,无法发文章。鉴于样品的重要性,非常有必要对样品进行详细且规范的记录,方便他人也方便自…

Java 线上机器 CPU 100 的一次排查过程

文章目录1. 问题发生2. 数据库连接关闭问题排查3. 问题的进一步排查4. 解决方法1. 问题发生 日常敲代码突然收到生产环境异常告警,线上有一台机器 CPU 使用率飙升到 100 触发扩容,工作群里一下子鸡飞狗跳。 出现问题,首先当然是查看监控和日…

在群晖NAS上搭建导航页_通过Web Station搭建

一、业务需求 1.1、需求说明 我们在使用群晖NAS的过程中,随着时间的推移会安装各种各样的软件内容和管理工具,而这些内容又都是一些网页界面(特别是一些在Docker中搭建的工具)时间久了我们也记不住那么多工具的Web界面地址&#…

激活Windows时出现错误代码0xC004C003怎么办?

Windows是我们最常见的电脑操作系统,那么如果我们在尝试激活Windows时出现错误代码0xC004C003,应该如何解决? 什么是Windows激活错误0xC004C003,出现该错误的原因是什么? Windows操作系统为了抑制盗版软件&#xff0c…

3D建模就业前景如何?加班多吗?值不值得入行

加班其实都还好🤔,因为这个岗位是按照项目进度考核(算钱)的,老手做一个模型要5,6个小时,新手可能需要10个小时,新人刚入行,做东西效率跟不上😰需要加班来弥补是肯定有的事…

SpringMVC-整合详解

SpringMVC-整合详解 MVC 什么是MVC? 它是一种开发模式,它是模型视图控制器的简称。所有的web应用都是基于MVC开发的 M: 模型层,它是模型视图控制器的简称。所有的web应用都是基于MVC开发 V: 视图层,html、javascript、vue等都是视图层,用…

高校实验室设备管理系统设计与实现-计算机毕业设计源码+LW文档

数据库代码: /* Navicat MySQL Data Transfer Source Server : mysql5 Source Server Version : 50562 Source Host : localhost:3306 Source Database : ssmgxsyssbglxthsg3511cg ​ Target Server Type : MYSQL Target Server Versio…

Linux磁盘分区和管理

文章目录一 添加硬盘,创建Linux分区1.首先准备一块新的硬盘2.检查系统是否识别了硬盘3.对磁盘进行分区3-1 创建MBR磁盘分区3-2 创建文件系统3-3 挂载文件系统二 创建交换空间2-1 创建分区2-2 设置分区类型2-3 格式化交换空间2-4 激活交换空间三 删除磁盘的分区3-1 备…

【GPU】Nvidia CUDA 编程高级教程——利用蒙特卡罗法求解近似值(CUDA-Aware MPI)

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…

11.24直播预告 | AIGC,看热闹不如看门道

如果把AI比作既富含能源,又无限神秘的海域,那么AIGC这条近半年内流经学术界和创投圈的支流,也无疑既带来了无数机遇,又蕴藏未知风险。 几天前,将门-TechBeat社区的专题(《AIGC的八大前沿创新》)…

Allegro基本规则设置指导书

Allegro基本规则设置指导书 下面介绍基本规则设置指导书之Analysis Modes 点击set-up-constrains-Modes 调出Analysis Modes,这个是所有DRC的总开关 下面介绍常用的一些开关设置 Design Options (Soldermask) 从上往下 阻焊到阻焊的间距 阻焊到pad和走线间距 阻焊到shape…

leecode #加一#二进制求和

题目描述: 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 分析:对数…

简单版的采用前后端分离模式实现SpingBoot新增查询功能

目录 后端代码编写 前端代码编写 首页展示: 新增: 开发工具:IDEA、HbuilderX 技术点:后端:SpringBoot,前端:ElementUIvue,采用前后端分离模式实现。 后端代码编写 目录: 代码…

多线程高并发笔记

一、基础知识 1. 线程打断的三种方法 interrupt() 打断某个线程(其实只是设置一个标志位)isInterrupted() 查询某线程是否被打断过(查询是否设置了标志位)static interrupted() 查询当前线程是否被打断过,并重置打断…

计算机毕业设计ssm+vue基本微信小程序的今日菜谱系统

项目介绍 谈到外出就餐,我们除了怕排队,也怕这家餐厅的服务员不够用,没人为我们点餐,那么一餐饭排队一小时,点餐恐怕也要花个半小时,这样不仅给消费者的用餐体验大打折扣同时也给商家的口碑造成了严重负面的影响,所以开发今日菜谱微信小程序系统是必须也是必然的。 本系统采用微…