1、为什么要做这一期
- 需要理解模糊检测的本质,为什么下面两种方法都可以用来进行模糊检测;
- 理解了模糊的本质之后,可以推向一些如:无纹理检测、噪声检测等等领域;
- 可能一些实验、项目等在预处理阶段设置个模糊检测对后续的后处理会有很大的帮助。
1.1 什么是模糊检测
在日常生活中,摄像产品在拍照或者录视频时,如果移动过快就会出现模糊的图片或者视频,这是因为移动速度大于了CCD或CMOS成像单元单帧感光时间,使得感光元件并没有完全记录当前帧的全部色彩信息,就会导致模糊的场景。 那既然出现了模糊的图片,那就有两种解决思路: 1、自动检测模糊图片,然后删掉; 2、将模糊图片进行复原(这是另外单独的领域,本文不做介绍)。
1.2 总概述:
本博客介绍两种模糊检测:1)拉普拉斯方差;2)快速傅里叶变化;两种都利用了模糊图像的本质,不过考虑方式有所不同。拉普拉斯方差是从空间域出发,分析出模糊图像的梯度比较小;快速傅里叶变化则转到了频域进行处理分析,得到模糊图像的频率一定很低。
2、拉普拉斯方差
2.1 思路
模糊图像的整体梯度一定很小 -> 想到使用 Sobel 和 Scharr 算子,最后想到了使用拉普拉斯(应该是计算量更少选的它) 详细描述: 这种方法有效的原因是拉普拉斯算子本身的定义,它用于测量图像的二阶导数。拉普拉斯算子突出显示包含快速强度变化的图像区域。这里的假设是,如果图像包含高方差,那么响应的范围很广,代表正常的对焦图像。但是如果方差非常低,则响应的范围很小,表明图像中的边缘非常少。众所周知,图像越模糊,边缘就越少。
但是,这里的技巧是设置正确的阈值,该阈值是一个经验值。阈值太低,如果不是,会错误地将图像标记为模糊。阈值太高,那么实际上模糊的图像将不会被标记为模糊。 代码很简单,只需要三行:
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
value = cv2.Laplacian(image, cv2.CV_64F).var()
然后设定阈值,如果大于value,表示清晰图像,如果小于value表示模糊图像。
3 快速傅里叶变换(FFT)
拉普拉斯方法需要经验值手动调整来定义图像模糊与否,阈值设的好与坏直接影响到结果,而且不好设置这个参数,可能不同的场景都得换。
3.1 什么是快速傅立叶变换 (FFT)?
快速傅立叶变换是一种用于计算离散傅立叶变换的便捷数学算法。它用于将信号从一个域转换为另一个域。 在计算机视觉方面,我们经常将 FFT 视为一种图像处理工具,可以在两个域中表示图像:
因此,FFT 以实部和虚部两种形式表示图像。
代码
def detect_blur_fft(image, size=60, thresh=10, vis=False):
# 输入: image:我们用于模糊检测的输入图像
# size:围绕图像中心点的半径大小,我们将对其进行 FFT 移位归零
# 将与幅度的平均值进行比较的值,以确定图像是否被认为是模糊的
(h, w) = image.shape
(cX, cY) = (int(w / 2.0), int(h / 2.0)) #导出中心 (x, y) 坐标
fft = np.fft.fft2(image) #计算 FFT 以找到频率变换
fftShift = np.fft.fftshift(fft) # 然后移位零频率分量(即直流分量位于左上角)到中心
fftShift[cY - size:cY + size, cX - size:cX + size] = 0 #将 FFT 移位的中心区域清零(即,删除低频率)
fftShift = np.fft.ifftshift(fftShift) #应用逆移使得低频再次到左上角
recon = np.fft.ifft2(fftShift) #逆FFT
magnitude = 20 * np.log(np.abs(recon)) #计算重建图像的幅度值,
mean = np.mean(magnitude) #计算幅度值的平均值
return (mean, mean <= thresh) #如果平均值小于阈值,图像将被视为“模糊”,
参考: [1] Variance of the Laplacian [2] Detecting blur in images with FFT
|