针对图片的清晰度识别,针对数据量比较大,对性能要求较高时,简单可靠的算法尤为重要,因此,经过对比,发现SSIM的算法可以在结合图片的结构,亮度,对比度三个条件下对图片进行分析。
step1:先将图片预处理裁剪
首先说明下我引用的用的python包:
import numpy as np
import math
import cv2
import urllib
裁剪图片视情况而定,主要结合业务需求将图片的大小裁剪成相同的尺寸,便于比较,因为我处理的大部分是新闻图片,因此将图片裁剪成512*400,并将彩色图片处理灰度化;
def imgPreHandle(img,img_witdth,img_height,resize_width=512,resize_height=480):
"""
将图片缩放到同样的尺寸
:param img: 图片
:param img_witdth: 图片的宽度
:param img_height: 图片的宽度高度
:param resize_width: 图片裁剪的宽度
:param resize_height 图片裁剪的高度
:return:
"""
# x = img_witdth
# y = img_height
x,y,z = img.shape
new_pic = img
if ((x>=resize_height) & (y>=resize_width))|((x<resize_height) & (y<resize_width)):
new_pic = img
elif (x<resize_height) & (y>=resize_width) :
new_pic = img[:, int((y/2)-(resize_width/2)):int((y/2) + (resize_width/2))]
elif (x>=resize_height) & (y<resize_width):
new_pic = img[int((x/2)-(resize_height/2)):int((x/2) + (resize_height/2)), :]
elif (x >= resize_height) & (y < resize_width):
new_pic = img[int((x / 2) - (resize_height / 2)):int((x / 2) + (resize_height / 2)), :]
new_picture = cv2.resize(new_pic, (resize_height, resize_width))
if len(new_picture.shape) == 3:
gray = rgb2gray(new_picture)
else:
gray = new_picture
return gray
step2: 对图像进行分块处理
首先对图片进行分块处理,视情况而定,这里将整个图片均匀分为9块大小,每块为11*11的大小,对每块图片采用ssimFunction函数处理,计算SSIM,与传统的ssim不同的是,我增加了一步利用函数entropyFunc计算信息熵的过程。
(1)在ssimFunction函数中先对每一小块图片进行高斯处理,然后分别对原图和高斯模糊后图片进行sobel边缘提取。
(2)计算每一小块的SSIM和信息熵大小
(3)通过对所有小块,按照信息熵进行片排名,然后取Top(这里取top=10)SSIM做均值。最后1-均值即为清晰度得分。
def img_ssimRecog(img, len_s = 11):
"""
图片处理
:param img: 图片
:param len_s: 图片每个小块尺寸
:return:
"""
X_org, Y_org = img.shape
res_list = []
for i in range(0, int(X_org), int(X_org / len_s)+3):
for j in range(0, int(Y_org), int(Y_org / len_s)+3):
res_list.append(ssimFunction(img[i:i + len_s, j:j + len_s]))
res_list = np.array(res_list)
res_list_sort = res_list[np.lexsort(-res_list.T)]
res_list = res_list_sort[:, :1]
res = np.mean(res_list[:10])
if res < 0.0:
res = 0.0
return 1 - res
其中信息熵的求解函数entropyFunc如下所示:
def entropyFunc(img):
"""
熵函数
:param img: 图片
:return:
"""
res = 0
tmp = [0] * 256
img_list = []
for i in range(len(img)):
img_list.extend(map(int, img[i]))
img_list_set = set(img_list)
for i in img_list_set:
tmp[i] = float(img_list.count(i))/ 256
for i in range(len(tmp)):
if (tmp[i] == 0):
res = res
else:
res = float(res - tmp[i] * (math.log(tmp[i]) / math.log(2.0)))
return res
求解ssim的函数如下所示:
def ssimFunction(img):
"""
ssim 算法
:param img: 图片
:return:
"""
x, y = img.shape
resEntropy = entropyFunc(img)
TR = cv2.GaussianBlur(img, (5,5),3)
G = cv2.Sobel(img,cv2.CV_16S,2,2)/5
Gr = cv2.Sobel(TR,cv2.CV_16S,2,2)/5
Ux = np.mean(G)
Uy = np.mean(Gr)
Vx = np.var(G)
Vy = np.var(Gr)
Vxy = (1 / (x * y - 1)) * np.sum((G - Ux) * (Gr - Uy))
R = 255
K1 = 0.03
K2 = 0.01
c1 = (K1 * R) ** 2
c2 = (K2 * R) ** 2
# -SSIM
A1 = 2 * Ux * Uy + c1
A2 = 2 * Vxy + c2
B1 = Ux ** 2 + Uy ** 2 + c1
B2 = Vx + Vy + c2
SSIM = (A1 * A2) / (B1 * B2)
return SSIM, resEntropy
效果如下所示:
参考文献:
1、https://blog.csdn.net/ecnu18918079120/article/details/60149864
2、https://blog.csdn.net/chaipp0607/article/details/70158835