使用OpenCV进行模糊检测(拉普拉斯算子)
点击上方“3D视觉工坊”,选择“星标”
干货第一时间送达
来源:Opencv视觉实践
本文翻译自光头哥哥的博客:【Blur detection with OpenCV】。
本文仅作学习分享,原文链接:
https://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/
这只超可爱、超活跃家养小猎犬可能是有史以来拍照次数最多的狗。从8周大我们得到它的时候,到现在,不到3年的时间,我们已经收集了6000多张狗狗的照片。
在刚刚过去的这个周末,我坐下来,试图整理手机里大量的照片。这是一项艰巨的任务,而且我很快就注意到一个问题——有很多照片模糊程度过高。
现在,对于一般人来说,我认为他们会删除这些模糊的照片(或者至少将它们移到一个单独的文件夹中)——但作为一个计算机视觉科学家,这是不可能发生的。
相反,我编写了一个快速的Python脚本,用OpenCV执行模糊检测。
接下来,我将向你展示如何使用OpenCV、Python和Laplacian算子计算图像中的模糊量。在这篇文章的结尾,你将能够应用Laplacian方法到你自己的照片来检测模糊的程度。
拉普拉斯变换的方差
图1:用Laplacian算子卷积输入图像
在研究如何检测图像中的模糊程度时,我的第一步是阅读优秀的综述论文,即【形状-聚焦测量算子分析[2013 Pertuz等]】。在Pertuz等人的论文中,回顾了近36种估计图像焦距程度的不同方法。
https://www.semanticscholar.org/paper/Analysis-of-focus-measure-operators-for-Pertuz-Puig/8c675bf5b542b98bf81dcf70bd869ab52ab8aae9?p2df
如果你有信号处理方面的背景,首先要考虑的方法是计算图像的快速傅里叶变换,然后检查低频和高频的分布:如果图像只有有少量的高频,那么图像就会被认为是模糊的。然而,定义什么算低数量的高频或者什么是高数量的高频是相当困难的。
相反,如果我们可以计算一个单一的浮点值来表示一个给定图像的模糊程度,不是很好吗?
Pertuz等人回顾了许多计算这种“模糊度度量”的方法,其中一些方法简单而直接,仅使用基本的灰度像素强度统计,另一些更先进和基于特征的方法,评估图像的局部二值模式。
快速浏览完这篇论文后,我找到了我一直在寻找的理想算法:pecch - pacheco等人在他们2000年ICPR论文《亮场显微镜中的硅藻自动聚焦:比较研究》中提出的Laplacian的变化。
方法很简单。简单。有良好的推理。并且只需要一行代码就可以实现:
cv2.Laplacian(image, cv2.CV_64F).var()
你只需采取一个图像的单一通道(大概灰度)和卷积它与以下3 x 3的内核:
然后取响应的方差(即标准差的平方)。
如果方差低于预先定义的阈值,则认为图像模糊;否则,图像不会模糊。
这种方法有效的原因是由于Laplacian算子本身的定义,它用于测量图像的二阶导数。拉普拉斯算子突出显示图像中包含快速梯度变化的区域,很像Sobel和Scharr算子。和这些算子一样,Laplacian也经常用于边缘检测。这里的假设是,如果一幅图像的方差较高,那么就说明图像有广泛的响应,包括类边和非类边,这是一幅正常的聚焦图像的代表。但如果方差很低,那么就会有很小的响应扩散,这表明图像中几乎没有边缘。而图像越模糊,边缘就越少。所以可以用来检测是否模糊。
显然,这里的关键是设置正确的阈值,而阈值的设置与应用到的图像集相关。如果阈值过低,你就会错误地将原本不模糊的图像标记为模糊。如果阈值过高,那么实际上模糊的图像将不会被标记为模糊。这种方法只有在非常稳定的图像集(同一类型)中应用良好。
检测图像中模糊的数量
所以现在我们已经明确了将要使用的方法:计算一个单一的度量来表示一个给定的图像是多么“模糊”,让我们看看我们的数据集以下12张图像:
图3:我们的图像集。有些模糊,有些则不然。我们的目标是使用OpenCV进行模糊检测并将图像标记为模糊。
正如你所看到的,有些图像是模糊的,有些则不是。我们的目标是正确地标记每个图像模糊或非模糊。
有了这些,打开一个新文件,命名为detect_blur.py,让我们打开代码:
# import the necessary packages
from imutils import paths
import argparse
import cv2
def variance_of_laplacian(image):
# compute the Laplacian of the image and then return the focus
# measure, which is simply the variance of the Laplacian
return cv2.Laplacian(image, cv2.CV_64F).var()
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=True,
help="path to input directory of images")
ap.add_argument("-t", "--threshold", type=float, default=100.0,
help="focus measures that fall below this value will be considered 'blurry'")
args = vars(ap.parse_args())
我们从在第2-4行上导入必要的包开始。如果你还没有我的imutils包在你的机器上,你会想现在安装:
$ pip install imutils
从这里开始,我们将在第6行定义variance_of_laplacian函数。这个方法将我们想要计算焦距的图像(假设为单个通道,例如灰度图像)作为参数。第9行简单地用3 x 3 Laplacian运算符对图像进行卷积,并返回方差。
第12-17行解析命令行参数。我们需要的第一个命令是——images,它是指向包含我们想要测试是否模糊的图像数据集的目录的路径。
我们还将定义一个可选参数——thresh,它是我们将用于模糊测试的阈值。如果一个给定图像的焦距测量低于这个阈值,我们将标记图像为模糊。需要注意的是,您可能需要为自己的图像数据集调优这个值。100的值对于我的数据集似乎工作得很好,但是这个值对于图像的内容是非常主观的,所以您需要自己使用这个值来获得最优结果。
不管你信不信,最难的部分已经完成了!我们只需要写一点代码从磁盘加载图像,计算Laplacian的方差,然后将图像标记为模糊或非模糊:
# loop over the input images
for imagePath in paths.list_images(args["images"]):
# load the image, convert it to grayscale, and compute the
# focus measure of the image using the Variance of Laplacian
# method
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
fm = variance_of_laplacian(gray)
text = "Not Blurry"
# if the focus measure is less than the supplied threshold,
# then the image should be considered "blurry"
if fm < args["threshold"]:
text = "Blurry"
# show the image
cv2.putText(image, "{}: {:.2f}".format(text, fm), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Image", image)
key = cv2.waitKey(0)
我们从第2行开始对图像目录进行循环。对于这些图像,我们将从磁盘加载,将其转换为灰度,然后使用OpenCV应用模糊检测(第6-9行)。
在焦点测量超过命令行参数提供的阈值的情况下,我们将把图像标记为“模糊”。
最后,第3517-20行将文本和计算结果写到图像上,并将结果显示在我们的屏幕上。
使用OpenCV进行模糊检测
现在我们已经编写了detect_blur.py脚本,让我们尝试一下。打开一个shell并发出以下命令:
$ python detect_blur.py --images images
这张照片的计算值是83.17,低于我们的阈值100;因此,我们正确地将该图像标记为模糊。
这幅图像的计算值为64.25,这也使得我们将其标记为“模糊”。
图6的计算值很高,为1004.14—比前两幅图高了几个数量级。这幅图像显然是非常清晰的。
总结
在这篇博文中,我们学习了如何使用OpenCV和Python执行模糊检测。
我们实现了计算Laplacian方法的方差,得到一个浮点值来表示图像的“模糊”程度。这种方法快速、简单、易于应用——我们只需用Laplacian算子对输入图像进行卷积并计算方差。如果方差低于预先定义的阈值,我们将图像标记为“模糊”。
需要注意的是,阈值是正确调优的一个关键参数,您经常需要根据每个数据集对其进行调优。
本文仅做学术分享,如有侵权,请联系删文。
下载1
在「3D视觉工坊」公众号后台回复:3D视觉,即可下载 3D视觉相关资料干货,涉及相机标定、三维重建、立体视觉、SLAM、深度学习、点云后处理、多视图几何等方向。
下载2
在「3D视觉工坊」公众号后台回复:3D视觉github资源汇总,即可下载包括结构光、标定源码、缺陷检测源码、深度估计与深度补全源码、点云处理相关源码、立体匹配源码、单目、双目3D检测、基于点云的3D检测、6D姿态估计源码汇总等。
下载3
在「3D视觉工坊」公众号后台回复:相机标定,即可下载独家相机标定学习课件与视频网址;后台回复:立体匹配,即可下载独家立体匹配学习课件与视频网址。
重磅!3DCVer-学术论文写作投稿 交流群已成立
扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。
同时也可申请加入我们的细分方向交流群,目前主要有3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流等微信群。
一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。
▲长按加微信群或投稿
▲长按关注公众号
3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近2000星球成员为创造更好的AI世界共同进步,知识星球入口:
学习3D视觉核心技术,扫描查看介绍,3天内无条件退款
圈里有高质量教程资料、可答疑解惑、助你高效解决问题
觉得有用,麻烦给个赞和在看~
推荐阅读
-
python中使用OpenCV进行人脸检测的例子
-
Android OpenCV使用2_使用OpenCV并进行人脸检测
-
OpenCV图像处理教程C++(十五)边缘检测算法--sobel算子、拉普拉斯算子、Canny算子
-
【OpenCV】边缘检测:Sobel、拉普拉斯算子
-
python—opencv图像膨胀|图像腐蚀|图像边缘检测sobel算子/拉普拉斯算子/canny算子
-
【OpenCV3经典编程100例】(08)边缘检测:拉普拉斯算子Laplacian()
-
使用OpenCV进行模糊检测(拉普拉斯算子)
-
使用OpenCV进行模糊检测(拉普拉斯算子)
-
python中使用OpenCV进行人脸检测的例子
-
python中使用OpenCV进行人脸检测的例子