人脸模糊程度评价指标

1.拉普拉斯方差算法——百度AIP Face的人脸检测接口返回值

参考资料

做图片的清晰度的检测,即取得图片的模糊度,值越小就越模糊。
百度AIP face进行人脸检测的同时会返回很多参数来判断人脸的可信度,光照,角度,及人员的年龄性别等等,也包括了模糊程度。

百度AIP人脸检测返回示例

  1. {
  2. "result_num": 1,
  3. "result": [
  4. {
  5. "location": {
  6. "left": 117,
  7. "top": 131,
  8. "width": 172,
  9. "height": 170
  10. },
  11. "face_probability": 1,
  12. "rotation_angle": 2,
  13. "yaw": -0.34859421849251,
  14. "pitch": 2.3033397197723,
  15. "roll": 1.9135693311691,
  16. "landmark": [
  17. {
  18. "x": 161.74819946289,
  19. "y": 163.30244445801
  20. },
  21. ...
  22. ],
  23. "landmark72": [
  24. {
  25. "x": 115.86531066895,
  26. "y": 170.0546875
  27. },
  28. ...
  29. ],
  30. "age": 29.298097610474,
  31. "beauty": 55.128883361816,
  32. "expression": 1,
  33. "expression_probablity": 0.5543018579483,
  34. "gender": "male",
  35. "gender_probability": 0.99979132413864,
  36. "glasses": 0,
  37. "glasses_probability": 0.99999964237213,
  38. "race": "yellow",
  39. "race_probability": 0.99999976158142,
  40. "qualities": {
  41. "occlusion": {
  42. "left_eye": 0,
  43. "right_eye": 0,
  44. "nose": 0,
  45. "mouth": 0,
  46. "left_cheek": 0.0064102564938366,
  47. "right_cheek": 0.0057411273010075,
  48. "chin": 0
  49. },
  50. "blur": 1.1886881756684e-10,
  51. "illumination": 141,
  52. "completeness": 1,
  53. "type": {
  54. "human": 0.99935841560364,
  55. "cartoon": 0.00064159056637436
  56. }
  57. }
  58. }
  59. ],
  60. "log_id": 2493878179101621
  61. }

可通过人脸检测接口,基于以下字段和对应阈值,进行质量检测的判断,以保证人脸质量符合后续业务操作要求。

指标 字段与解释 推荐数值界限

  1. 遮挡范围 occlusion0~1),0为无遮挡,1是完全遮挡
  2. 含有多个具体子字段,表示脸部多个部位
  3. 通常用作判断头发、墨镜、口罩等遮挡 left_eye : 0.6, #左眼被遮挡的阈值
  4. right_eye : 0.6, #右眼被遮挡的阈值
  5. nose : 0.7, #鼻子被遮挡的阈值
  6. mouth : 0.7, #嘴巴被遮挡的阈值
  7. left_check : 0.8, #左脸颊被遮挡的阈值
  8. right_check : 0.8, #右脸颊被遮挡的阈值
  9. chin_contour : 0.6, #下巴被遮挡阈值
  10. 模糊度范围 Blur0~1),0是最清晰,1是最模糊 小于0.7
  11. 光照范围 illumination0~255
  12. 脸部光照的灰度值,0表示光照不好
  13. 以及对应客户端SDK中,YUVY分量 大于40
  14. 姿态角度
  15. Pitch:三维旋转之俯仰角度[-90(上), 90(下)]
  16. Roll:平面内旋转角[-180(逆时针), 180(顺时针)]
  17. Yaw:三维旋转之左右旋转角[-90(左), 90(右)] 分别小于20
  18. 人脸完整度 completeness01),0代表完整,1代表不完整 小于0.4
  19. 人脸大小 人脸部分的大小
  20. . 建议长宽像素值范围:8080~200200 人脸部分不小于100*100像素

百度AIP中模糊度的计算方法:拉普拉斯方差算法(Variance of the Laplacian)

利用OpenCV和拉普拉斯算子来计算图片中的模糊量
只需要将图片中的某一通道(但一般用灰度值)用下面的拉普拉斯掩模做卷积运算:
face_blur_detection - 图1

用拉普拉斯算子与输入图像做卷积,然后计算方差(即标准差的平方)。
如果某图片方差低于预先定义的阈值,那么该图片就可以被认为是模糊的。高于阈值,就不是模糊的。
这种方法凑效的原因就在于拉普拉斯算子定义本身。它被用来测量图片的二阶导数,突出图片中强度快速变化的区域,和 Sobel 以及 Scharr 算子十分相似。并且,和以上算子一样,拉普拉斯算子也经常用于边缘检测。
此外,此算法基于以下假设:如果图片具有较高方差,那么它就有较广的频响范围,代表着正常,聚焦准确的图片。但是如果图片具有有较小方差,那么它就有较窄的频响范围,意味着图片中的边缘数量很少。正如我们所知道的,图片越模糊,其边缘就越少。

代码如下:

  1. import cv2
  2. imagePath ='./data/y1.jpg'
  3. image = cv2.imread(imagePath)
  4. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  5. print('y1 blur:',cv2.Laplacian(gray, cv2.CV_64F).var())

存在问题:
图像y1:
face_blur_detection - 图2
图像y2:
face_blur_detection - 图3

运行结果:图像y1的blur值更高,即程序判断y1更清晰

  1. y1 blur: 1663.09841446
  2. y2 blur: 924.740511

原因分析:

  • 造成图片的模糊有2个原因,一种是目标快速移动,还一种是摄像机本身抖动
  • 目前监控摄像头造成的迷糊原因是目标快速移动,而背景不动
  • 拉普拉斯方差计算会使用拉普拉斯掩模对整张图做卷积运算,而背景不动的部分其实很清晰,只是移动的目标部分模糊罢了,这样整个模糊值就低了

改进:
获取人脸区域,只计算人脸区域的拉普拉斯卷积值。
face_blur_detection - 图4
face_blur_detection - 图5
运行结果:

  1. y1 blur: 418.203306267
  2. y2 blur: 1196.72339094

2. Brenner 梯度函数

Brenner梯度函数是最简单的梯度评价函数,它只是简单的计算相邻两个像素灰度差的平方,该函数定义如下:
face_blur_detection - 图6
其中:f(x,y) 表示图像f对应像素点(x,y)的灰度值,D(f)为图像清晰度计算结果(下同)。

代码:

  1. def Brenner(img):
  2. x, y = img.shape
  3. D = 0
  4. for i in range(x-2):
  5. for j in range(y-2):
  6. D += (img[i+2, j] - img[i, j])**2
  7. return D

3. Tenengrad 梯度函数

Tenengrad梯度函数采用Sobel算子分别提取水平和垂直方向的梯度,基于Tenengrad的图像清晰度定义如下:
face_blur_detection - 图7
G(x,y)的形式如下:
face_blur_detection - 图8
其中,T是给定的边缘检测阈值,Gx和Gy分别是像素点(x,y)处Sobel水平和垂直方向边缘检测算子的卷积。建议使用以下的Sobel算子模板来检测边缘:
face_blur_detection - 图9

代码:

  1. def Thenengrad(img):
  2. T = 50 # 边缘检测阈值
  3. Grad_value = 0
  4. Sx, Sy = 0
  5. x, y = img.shape
  6. for i in range(1,x-1):
  7. current_ptr = img[i,:] # 当前行
  8. pre_ptr = img[i-1,:] # 上一行
  9. next_ptr= img[i+1,:] # 下一行
  10. for j in range(1,y-1):
  11. Sx = pre_ptr[j - 1] * (-1) + pre_ptr[j + 1] + current_ptr[j - 1] * (-2) + current_ptr[j + 1] * 2 + next_ptr[j - 1] * (-1) + next_ptr[j + 1]; # x方向梯度
  12. Sy = pre_ptr[j - 1] + 2 * pre_ptr[j] + pre_ptr[j + 1] - next_ptr[j - 1] - 2 * next_ptr[j] - next_ptr[j + 1] # y方向梯度
  13. # 求总和
  14. G = sqrt(Sx * Sx + Sy * Sy)
  15. if G > T:
  16. Grad_value += G
  17. return Grad_value

4. SMD(灰度方差)函数

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

代码:

  1. def SMD(img):
  2. # 图像的预处理
  3. reImg = cv2.resize(img, (800, 900), interpolation=cv2.INTER_CUBIC)
  4. img2gray = cv2.cvtColor(reImg, cv2.COLOR_BGR2GRAY) # 将图片压缩为单通道的灰度图
  5. f=self._imageToMatrix(img2gray)/255.0
  6. x, y = f.shape
  7. D = 0
  8. for i in range(x - 1):
  9. for j in range(y - 1):
  10. D += np.abs(f[i+1,j]-f[i,j])+np.abs(f[i,j]-f[i+1,j])
  11. return D

5. SMD2 (灰度方差乘积)函数

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

  1. def SMD2(img):
  2. # 图像的预处理
  3. reImg = cv2.resize(img, (800, 900), interpolation=cv2.INTER_CUBIC)
  4. img2gray = cv2.cvtColor(reImg, cv2.COLOR_BGR2GRAY) # 将图片压缩为单通道的灰度图
  5. f=self._imageToMatrix(img2gray)/255.0
  6. x, y = f.shape
  7. D = 0
  8. for i in range(x - 1):
  9. for j in range(y - 1):
  10. D += np.abs(f[i+1,j]-f[i,j])*np.abs(f[i,j]-f[i,j+1])
  11. return D

6. 方差函数

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

  1. def _SMD2Detection(img):
  2. # 图像的预处理
  3. reImg = cv2.resize(img, (800, 900), interpolation=cv2.INTER_CUBIC)
  4. img2gray = cv2.cvtColor(reImg, cv2.COLOR_BGR2GRAY) # 将图片压缩为单通道的灰度图
  5. f = self._imageToMatrix(img2gray)
  6. D = np.var(f)
  7. return D

7. 能量梯度函数

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

8. Vollath函数

Vollath函数定义如下:
face_blur_detection - 图14
其中: u为整幅图像的平均灰度值,M和N分别为图像宽和高。
代码:

  1. def Vollath(img):
  2. # 图像的预处理
  3. reImg = cv2.resize(img, (800, 900), interpolation=cv2.INTER_CUBIC)
  4. img2gray = cv2.cvtColor(reImg, cv2.COLOR_BGR2GRAY) #
  5. f = self._imageToMatrix(img2gray)
  6. D = 0
  7. x,y=f.shape
  8. for i in range(x-1):
  9. for j in range(y):
  10. D += f[i,j]*f[i+1,j]
  11. D = D - x * y * np.mean(f)
  12. return D

9. 熵函数

基于统计特征的熵函数是衡量图像信息丰富程度的一个重要指标,有信息论可知,一幅图像 f 的信息量是由该图像的信息熵 D(f) 来度量:
face_blur_detection - 图15
其中:Pi 是图像中灰度值为i的像素出现的概率,L为灰度级总数(通常取值256)。根据Shannon信息论,熵最大时信息量最多。将此原理应用到对焦过程,D(f)越大则图像越清晰。熵函数灵敏度不高,依据图像内容不同容易出现与真实情况相反的结果。

代码:

  1. def Entropy(img):
  2. x, y = img.shape
  3. temp = np.zeros((1,256))
  4. # 对图像的灰度值在[0,255]上做统计
  5. for i in range(x):
  6. for j in range(y)
  7. if img[i,j] == 0:
  8. k = 1
  9. else:
  10. k = img(i,j)
  11. temp[0,k] = temp[0,k] + 1
  12. temp = temp / (x * y)
  13. # 由熵的定义做计算
  14. D = 0
  15. for i in range(1,256):
  16. if temp[0,i] != 0:
  17. D = D - temp[0,i] * log(temp[0,i],2)
  18. return D

10. JPEG: No-Reference Perceptual Quality Assessment of JPEG Compressed Images

在这篇文章中,作者【Zhou Wang】等针对JPEG压缩图片提出了一种新的无参图像质量评价方法。
JPEG图片是基于8x8块的DCT变换的编码技巧,它是有损的因为对DCT变换系数做量化的时候会产生量化误差。量化就会导致模糊和块效应。模糊主要是因为丢失了高频的DCT系数。块效应是由于块边界的不连续性,因为每个分块的量化是独立的。

我们用 f(x, y) 表示一幅图片,图片尺寸为 MxN,计算跨越每个水平线的信号差:
face_blur_detection - 图16
首先计算块效应,块效应的定义就是左右跨越边界的信号差的平均值:
face_blur_detection - 图17
然后计算块内信号差的平均值:
face_blur_detection - 图18
再计算zero-crossing(ZC)率,ZC是边界跨零的意思,也就是说相邻两个点的dh(x,y)值的乘积为负数,也就是一正一负,因此对于[1, N - 2]范围内的y,定义如下变量:
face_blur_detection - 图19
于是水平方向的ZC率定义如下:
face_blur_detection - 图20
同理,我们可以计算垂直方向的几个指标值Bv,Av和Zv,最后得到这几个指标的水平和垂直方向的平均值:
face_blur_detection - 图21
有很多方式把这几个指标联系起来组成一个质量评价模型。此处我们采用如下图像质量定义:
face_blur_detection - 图22
其中各个权值是从大量实验中提炼出来的模型参数。本文中所采用的参数值如下:
face_blur_detection - 图23

11. JPEG2:No-Reference Image Quality Assessment forJPEG/JPEG2000 Coding

这篇文章的作者在前面那篇文章的基础上,重新定义了新的质量指标:
face_blur_detection - 图24
其实 S 就是在10.中已经得到的质量评价值。

12. No-Reference Image Quality Assessment using Blur and Noise

图像质量受很多因素影响,例如:亮度、对比度、色调、边界、噪声、模糊等。在本文中,我们假定噪声和模糊是影响图像质量最重要的两个因素。简单起见,只对彩色图像的亮度分量做模糊和噪声监测。本文的图像质量评价算法框架图如下:
face_blur_detection - 图25
具体计算方法见:图像清晰度的评价及分析

Remark:

  • 与主观感知一致且鲁棒性较强:Brenner、Tenengrad、SMD2、Energy、JPEG、JPEG2
  • Variance、Vollath算法所得数据非常接近,无法分辨出图像质量
  • Vollat、Entropy算法失误比较多
  • SMD、EAV在图片质量都非常好,肉眼难分辨的情况下存在失误,这种失误可以接受
  • Laplacian、Variance 在判断质量非常差的图片时出现失误

https://gist.github.com/JuneoXIE/d595028586eec752f4352444fc062c44