转载自:https://zhuanlan.zhihu.com/p/97024018,本文只做个人记录学习使用,版权归原作者所有。

需求:在一堆图像中找到模糊图像,背景虚化(景深模式)的照片定义为清晰照片。

传统的图像清晰度评价算法:

Tenengrad 梯度函数

Tenengrad 梯度函数采用Sobel算子分别提取水平和垂直方向的梯度值,基与Tenengrad 梯度函数的图像清晰度定义如下:

G(x,y) 的形式如下:

其中:T是给定的边缘检测阈值,Gx和Gy分别是像素点(x,y)处Sobel水平和垂直方向边缘检测算子的卷积,建议使用以下的Sobel算子模板来检测边缘:

python程序实现:

Laplacian 梯度函数

Laplacian 梯度函数与Tenengrad梯度函数基本一致,用Laplacian算子替代Sobel算子即可,该算子定义如下:

因此基于Laplacian 梯度函数的图像星清晰度的定义如下:

其中G(x,y)是像素点(x,y)处Laplacian算子的卷积。

python程序实现:

#Laplacian梯度函数计算
def Laplacian(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''return cv2.Laplacian(img,cv2.CV_64F).var()

SMD(灰度方差)函数

当完全聚焦时,图像最清晰,图像中的高频分量也最多,故可将灰度变化作为聚焦评价的依据,灰度方差法的公式如下:

python程序实现:

#SMD梯度函数计算
def SMD(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(1, shape[0]-1):for y in range(0, shape[1]):out+=math.fabs(int(img[x,y])-int(img[x,y-1]))out+=math.fabs(int(img[x,y]-int(img[x+1,y])))return out

SMD2 (灰度方差乘积)函数

灰度差分评价函数具有较好的计算性能,但其缺点也很明显,即在焦点附近灵敏度不高,即该函数在极值点附近过于平坦,从而导致聚焦精度难以提高。在文章《一种快速高灵敏度聚焦评价函数》中提出了一种新的评价函数,称之为灰度方差乘积法,即对每一个像素领域两个灰度差相乘后再逐个像素累加,该函数定义如下:

python程序实现:

#SMD2梯度函数计算
def SMD2(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-1):for y in range(0, shape[1]-1):out+=math.fabs(int(img[x,y])-int(img[x+1,y]))*math.fabs(int(img[x,y]-int(img[x,y+1])))return out

Brenner 梯度函数

Brenner梯度函数是最简单的梯度评价函数,它只是简单的计算相邻两个像素灰度差的平方,该函数定义如下:

其中:f(x,y) 表示图像f对应像素点(x,y)的灰度值,D(f)为图像清晰度计算结果.

python程序实现:

#brenner梯度函数计算
def brenner(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-2):for y in range(0, shape[1]):out+=(int(img[x+2,y])-int(img[x,y]))**2return out

方差函数

因为清晰聚焦的图像有着比模糊图像更大的灰度差异,可以将方差函数作为评价函数:

其中:μ为整幅图像的平均灰度值,该函数对噪声比较敏感,图像画面越纯净,函数值越小。

python程序实现:

#方差函数计算
def variance(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''out = 0u = np.mean(img)shape = np.shape(img)for x in range(0,shape[0]):for y in range(0,shape[1]):out+=(img[x,y]-u)**2return out

能量梯度函数

能量梯度函数更适合实时评价图像清晰度,该函数定义如下:

python程序实现:

#energy函数计算
def energy(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-1):for y in range(0, shape[1]-1):out+=((int(img[x+1,y])-int(img[x,y]))**2)*((int(img[x,y+1]-int(img[x,y])))**2)return out

Vollath函数

Vollath函数定义如下:

其中:μ为整幅图像的平均灰度值,M和N分别为图像宽和高。

python程序实现:

#Vollath函数计算
def Vollath(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)u = np.mean(img)out = -shape[0]*shape[1]*(u**2)for x in range(0, shape[0]-1):for y in range(0, shape[1]):out+=int(img[x,y])*int(img[x+1,y])return out

熵函数

基于统计特征的熵函数是衡量图像信息丰富程度的一个重要指标,有信息论可知,一幅图像 f 的信息量是由该图像的信息熵 D(f) 来度量:

其中:Pi 是图像中灰度值为i的像素出现的概率,L为灰度级总数(通常取值256)。根据Shannon信息论,熵最大时信息量最多。将此原理应用到对焦过程,D(f)越大则图像越清晰。熵函数灵敏度不高,依据图像内容不同容易出现与真实情况相反的结果。

python程序实现:

#entropy函数计算
def entropy(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''out = 0count = np.shape(img)[0]*np.shape(img)[1]p = np.bincount(np.array(img).flatten())for i in range(0, len(p)):if p[i]!=0:out-=p[i]*math.log(p[i]/count)/countreturn out

以上算法利用python实现,主要基于opencv,numpy, math库 ,以下是完整代码:

import cv2
import numpy as np
import math#brenner梯度函数计算
def brenner(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-2):for y in range(0, shape[1]):out+=(int(img[x+2,y])-int(img[x,y]))**2return out#Laplacian梯度函数计算
def Laplacian(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''return cv2.Laplacian(img,cv2.CV_64F).var()#SMD梯度函数计算
def SMD(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(1, shape[0]-1):for y in range(0, shape[1]):out+=math.fabs(int(img[x,y])-int(img[x,y-1]))out+=math.fabs(int(img[x,y]-int(img[x+1,y])))return out#SMD2梯度函数计算
def SMD2(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-1):for y in range(0, shape[1]-1):out+=math.fabs(int(img[x,y])-int(img[x+1,y]))*math.fabs(int(img[x,y]-int(img[x,y+1])))return out#方差函数计算
def variance(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''out = 0u = np.mean(img)shape = np.shape(img)for x in range(0,shape[0]):for y in range(0,shape[1]):out+=(img[x,y]-u)**2return out#energy函数计算
def energy(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)out = 0for x in range(0, shape[0]-1):for y in range(0, shape[1]-1):out+=((int(img[x+1,y])-int(img[x,y]))**2)*((int(img[x,y+1]-int(img[x,y])))**2)return out#Vollath函数计算
def Vollath(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''shape = np.shape(img)u = np.mean(img)out = -shape[0]*shape[1]*(u**2)for x in range(0, shape[0]-1):for y in range(0, shape[1]):out+=int(img[x,y])*int(img[x+1,y])return out#entropy函数计算
def entropy(img):''':param img:narray 二维灰度图像:return: float 图像越清晰越大'''out = 0count = np.shape(img)[0]*np.shape(img)[1]p = np.bincount(np.array(img).flatten())for i in range(0, len(p)):if p[i]!=0:out-=p[i]*math.log(p[i]/count)/countreturn outdef main(img1, img2):print('Brenner',brenner(img1),brenner(img2))print('Laplacian',Laplacian(img1),Laplacian(img2))print('SMD',SMD(img1), SMD(img2))print('SMD2',SMD2(img1), SMD2(img2))print('Variance',variance(img1),variance(img2))print('Energy',energy(img1),energy(img2))print('Vollath',Vollath(img1),Vollath(img2))print('Entropy',entropy(img1),entropy(img2))if __name__ == '__main__':#读入原始图像img1 = cv2.imread('./data/MotionL100H0_15.jpg')img2 = cv2.imread('./data/MotionL100H0_13.jpg')#灰度化处理img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)main(img1,img2)

c++实现请参考:

无参考图像的清晰度评价方法及c++实现 - 代码先锋网​www.codeleading.com

MATLAB实现请参考:

https://blog.csdn.net/kungfu_rabbit/article/details/90243838​blog.csdn.net

Reblur 二次模糊
如果一幅图像已经模糊了,那么再对它进行一次模糊处理,高频分量变化不大;但如果原图是清楚的,对它进行一次模糊处理,则高频分量变化会非常大。因此可以通过对待评测图像进行一次高斯模糊处理,得到该图像的退化图像,然后再比较原图像和退化图像相邻像素值的变化情况,根据变化的大小确定清晰度值的高低,计算结果越小表明图像越清晰,反之越模糊。这种思路可称作基于二次模糊的清晰度算法,其算法简化流程如下图:

NRSS 梯度结构相似度

python实现:

#encoding=utf-8
import cv2
import numpy as np
from skimage.measure import compare_ssimdef gauseBlur(img):img_Guassian = cv2.GaussianBlur(img,(7,7),0)return img_Guassiandef loadImage(filepath):img = cv2.imread(filepath, 0)  ##   读入灰度图return img
def showImage(img):cv2.imshow('image', img)cv2.waitKey(0)
def saveImage(path, img):cv2.imwrite(path, img)
def sobel(img):x = cv2.Sobel(img, cv2.CV_16S, 1, 0)y = cv2.Sobel(img, cv2.CV_16S, 0, 1)absX = cv2.convertScaleAbs(x)  # 转回uint8absY = cv2.convertScaleAbs(y)dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)return dst
def getBlock(G,Gr):(h, w) = G.shapeG_blk_list = []Gr_blk_list = []sp = 6for i in range(sp):for j in range(sp):G_blk = G[int((i / sp) * h):int(((i + 1) / sp) * h), int((j / sp) * w):int(((j + 1) / sp) * w)]Gr_blk = Gr[int((i / sp) * h):int(((i + 1) / sp) * h), int((j / sp) * w):int(((j + 1) / sp) * w)]G_blk_list.append(G_blk)Gr_blk_list.append(Gr_blk)sum = 0for i in range(sp*sp):mssim = compare_ssim(G_blk_list[i], Gr_blk_list[i])sum = mssim + sumnrss = 1-sum/(sp*sp*1.0)print(nrss)
def NRSS(path):image = loadImage(path)#高斯滤波Ir = gauseBlur(image)G = sobel(image)Gr = sobel(Ir)blocksize = 8## 获取块信息getBlock(G, Gr)
if __name__ == "__main__":filepath = "F:\\testpic\\new\\blurtest\\clear\\3.jpg"NRSS(filepath)

传统的图像模糊检测主要存在以下缺点:

1.模糊界限难以确定,需要定一个阈值去区分(根据应用场景确定)。

2.众多的算法那个算法更适合,需要去验证。

针对传统算法也有一些机器学习和深度学习的方法去解决:

机器学习方法:

  1. 使用拉普拉斯滤镜在输入图像中查找边缘
  2. 计算方差和已过滤图像像素值的最大值
  3. 高方差(和高最大值)表明边缘清晰可见,即图像清晰。低方差表明图像模糊。
  4. 基于Laplace的特征的图,我们注意到我们的两类(模糊和非模糊)是线性可分离的,然后利用SVM进行

实现代码:

#计算laplace算子
import numpy as np
from scipy.ndimage import variance
from skimage import io
from skimage.color import rgb2gray
from skimage.filters import laplace
from skimage.transform import resize# Load image
path = f'test_data/0001.jpg'
img = io.imread(path)# Resize image
img = resize(img, (400, 600))# Grayscale image
img = rgb2gray(img)# Edge detection
edge_laplace = laplace(img, ksize=3)# Print output
print(f"Variance: {variance(edge_laplace)}")
print(f"Maximum : {np.amax(edge_laplace)}")
#利用SVM进行分类
import numpy as npfrom sklearn import preprocessing, svm# start with the results from the previous script
sharp_laplaces = [ (variance(edge_laplace_sharp_1), np.amax(edge_laplace_sharp_1)), ... ]
blurry_laplaces = [ (variance(edge_laplace_blurry_1), np.amax(edge_laplace_blurry_1)), ... ]# set class labels (non-blurry / blurry) and prepare features
y = np.concatenate((np.ones((25, )), np.zeros((25, ))), axis=0)
laplaces = np.concatenate((np.array(sharp_laplaces), np.array(blurry_laplaces)), axis=0)# scale features
laplaces = preprocessing.scale(laplaces)# train the classifier (support vector machine)
clf = svm.SVC(kernel='linear', C=100000)
clf.fit(laplaces, y)# print parameters
print(f'Weights: {clf.coef_[0]}')
print(f'Intercept: {clf.intercept_}')# make sample predictions
clf.predict([[0.00040431, 0.1602369]])  # result: 0 (blurred)
clf.predict([[0.00530690, 0.7531759]])  # result: 1 (sharp)

深度学习方法:

针对模糊非模糊进行简单的二分类

数据集:

CERTH Image Blur Dataset - MKLab​mklab.iti.gr

方法参考:

priyabagaria/Image-Blur-Detection​github.com

模糊区域检测,利用奇异值分解(SVD):

https://github.com/fled/blur_detection​github.com

参考:

[1].https://blog.csdn.net/Real_Myth/article/details/50827940

[2].https://medium.com/snapaddy-tech-blog/mobile-image-blur-detection-with-machine-learning-c0b703eab7de

[3].https://github.com/Leezhen2014/python--/blob/master/BlurDetection.py

发布于 2019-12-13

模糊图像检测-无参考图像的清晰度评价相关推荐

  1. 无参考图像的清晰度评价方法 (图像清晰度的评价指标)

    无参考图像的清晰度评价方法 from: http://nkwavelet.blog.163.com/blog/static/227756038201461532247117 在无参考图像的质量评价中, ...

  2. 无参考图像的清晰度评价方法

    在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的重要指标,它能够较好的与人的主观感受相对应,图像的清晰度不高表现出图像的模糊.本文针对无参考图像质量评价应用,对目前几种较为常用的.具有代表性 ...

  3. 【CV系列】无参考图像的清晰度评价方法,附NRSS的matlab实现

    Date: 2018/3/11 参考:https://blog.csdn.net/real_myth/article/details/50827940 https://blog.csdn.net/wx ...

  4. 无参考图像的质量评价

    转自: http://nkwavelet.blog.163.com/blog/static/227756038201461532247117 在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的 ...

  5. 无参考图像清晰度评价

    转自: http://nkwavelet.blog.163.com/blog/static/227756038201461532247117 在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的 ...

  6. 无参考图像评价指标NIQE——自然图像质量

    无参考图像评价指标NIQE--自然图像质量评价器 NIQE(Natural Image Quality Evaluator) 为何引入NIQE NIQE的背景 NIQE算法的具体过程 代码实现 NIQ ...

  7. 无参考图像单张视频图像噪声检测C++ opencv

    参考博客:https://blog.csdn.net/watermelon1123/article/details/78093724 该博客介绍了两种无参考空间域图像噪点检测方法,并且给出两种算法的原 ...

  8. matlab无参考图像质量评价,无参考屏幕内容图像质量评价

    1 引言 1.1 研究背景及意义 随着计算机和移动互联网技术的快速发展, 多屏互动[.视频游戏[.远程教育等多客户端通信系统也得到了飞速的发展.在这类系统中, 各类终端之间可以相互通信, 以实现屏幕内 ...

  9. 图像处理:图像清晰度评价

    目录 0.实现效果 1.概述 2.模糊度分类 1.运动模糊 2.压缩模糊 3.高斯模糊 3.清晰度量化指标 Brenner 能量梯度函数(Energy of Gradient) ​编辑 Roberts ...

最新文章

  1. 数据结构 算法与应用C 语言描述第六章,数据结构算法与应用-C语言描述002.pdf
  2. Mysql-InnoDB 锁学习
  3. 算法-------寻找旋转排序数组中的最小值
  4. Linux文件IO深入剖析
  5. 成功解决Future Warning: The sklearn.neighbors.dist_metrics module is deprecated in version 0.22 and wil
  6. python range函数怎么表示无限_Python for循环与range函数的使用详解
  7. async中series的实现 javascript构件
  8. linux 下的csp 模块,linux kernel 中MIGRATE_TYPES的理解
  9. python websocket异步高并发_python – WebSocket聊天异步示例崩溃
  10. navicat 连接mysql is not allowed to connect to this mysql server
  11. sed 多行替换,多行模式处理字符串;一次替换
  12. Access2016学习2
  13. Java项目:SSM高校教职工差旅报销管理系统
  14. 通俗解释什么是NFT,NFT到底是什么
  15. 离线强化学习(Offline RL)系列1:离线强化学习原理入门
  16. 缓解过拟合(overfitting)的方法
  17. 011 dilate(膨胀)、erode(腐蚀)
  18. 刘同-《谁的青春不迷茫》
  19. 【C++】CGAL学习笔记
  20. 斐讯k3搭建nginx+php+MariaDB(mysql )的教程

热门文章

  1. WDS部署Windows
  2. 【操作系统】第六章-输入输出系统
  3. 流量与画像:消失掉的用户消费
  4. 微信小程序详细开发教程
  5. Codeforces 540B School Marks 【贪心构造】
  6. 【NOIP2012模拟10.25】剪草
  7. c语言进阶——c语言题目训练
  8. 代码坏味道与重构之冗赘的元素和夸夸其谈的通用性
  9. 混合(Blending)
  10. BUUCTF Misc [BJDCTF2020]鸡你太美 [BJDCTF2020]一叶障目 [SWPU2019]神奇的二维码 梅花香之苦寒来 [BJDCTF2020]纳尼