使用OpenCV进行图像的模糊检测

8

我正在处理图像的模糊检测。我在OpenCV中使用了拉普拉斯方差方法。

img = cv2.imread(imgPath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
value = cv2.Laplacian(gray, cv2.CV_64F).var()

在某些情况下,该函数失败,例如像素模糊。对于那些模糊的图像,它显示比实际清晰图像更高的值。是否有更好的方法来检测像素化以及运动模糊?
示例图像:
这张图片更清晰,但显示了266.79的值。

enter image description here

这张图片显示的是 446.51 的值。

enter image description here

此图像似乎更清晰,但仅显示值38.96

enter image description here

我需要将第一个和第三个分类为非模糊,而将第二个分类为模糊。

1
请发布示例图片,以便我们进行自己的测试。 - fmw42
1
没有具体的建议,但是谷歌的HDR+论文中提到他们使用“基于原始输入绿色通道梯度的简单度量标准。这遵循了一般策略,即幸运成像[Joshi和Cohen 2010]”。 - Sam Mason
@fmw42发布了示例图片,请查看。 - Yashasvi Raj Pant
仍然不明白为什么图像3的值如此之低。有任何想法吗? - Yashasvi Raj Pant
从技术上讲,第二张图像并没有模糊。实际上,它是一个低分辨率图像的放大版本,使用最近邻重采样技术。与模糊相反,这会产生清晰的边缘。因此,模糊测量技术将失败。 - user1196549
显示剩余4条评论
2个回答

8
我可能晚了回答这个问题,但是这里有一个潜在的方法。可以使用pypi中的blur_detector库来识别图像中清晰和模糊的区域。以下是创建该库的论文: https://arxiv.org/pdf/1703.07478.pdf 该库的操作方式是,在多个尺度上查看图像中的每个像素,并在每个尺度上执行离散余弦变换。然后过滤这些DCT系数,以便仅使用高频系数。在多个尺度上,所有高频DCT系数被融合在一起并排序,形成多尺度融合和排序的高频变换系数。选择这些排序系数的子集。这是一个可调参数,用户可以根据应用程序进行实验。所选DCT系数的输出随后通过最大池化发送以保留多个尺度的最大激活。这使得算法非常稳健,可以检测图像中的模糊区域。
这是我在您提供的图片中看到的结果: enter image description here 注:我使用了opencv默认的级联检测器中的人脸检测器来选择感兴趣区域。这两种方法的输出(空间模糊检测+人脸检测)可以用于获取图像的清晰度图。
在这里,我们可以看到在清晰的图像中,眼睛区域像素的强度非常高,而在模糊的图像中则很低。
您可以对此进行阈值处理,以识别哪些图像是清晰的,哪些图像是模糊的。
以下是生成上述结果的代码片段:
pip install blur_detector

import blur_detector
import cv2

if __name__ == '__main__':
    face_cascade = cv2.CascadeClassifier('cv2/data/haarcascade_frontalface_default.xml')

    img = cv2.imread('1.png', 0)
    blur_map1 = blur_detector.detectBlur(img, downsampling_factor=1, num_scales=3, scale_start=1)
    faces = face_cascade.detectMultiScale(img, 1.1, 4)
    for (x, y, w, h) in faces:
        cv2.rectangle(blur_map1, (x, y), (x + w, y + h), (255, 0, 0), 2)

    img = cv2.imread('2.png', 0)
    blur_map2 = blur_detector.detectBlur(img, downsampling_factor=1, num_scales=3, scale_start=1)
    faces = face_cascade.detectMultiScale(img, 1.1, 4)
    for (x, y, w, h) in faces:
        cv2.rectangle(blur_map2, (x, y), (x + w, y + h), (255, 0, 0), 2)

    img = cv2.imread('3.png', 0)
    blur_map3 = blur_detector.detectBlur(img, downsampling_factor=1, num_scales=3, scale_start=1)
    faces = face_cascade.detectMultiScale(img, 1.1, 4)
    for (x, y, w, h) in faces:
        cv2.rectangle(blur_map3, (x, y), (x + w, y + h), (255, 0, 0), 2)

    cv2.imshow('a', blur_map1)
    cv2.imshow('b', blur_map2)
    cv2.imshow('c', blur_map3)
    cv2.waitKey(0)

要了解关于模糊检测算法的详细信息,请查看此github页面:https://github.com/Utkarsh-Deshmukh/Spatially-Varying-Blur-Detection-python


在 OpenCV JS 中有没有相应的等效物? - sarfrazanwar
我不这么认为。因为这在opencv库中还没有可用。这是一个使用opencv的自定义Python库。 - Utkarsh Deshmukh

4
你可以尝试将阈值定义为浮点数,这样每个结果都会在阈值以下 == 模糊。但是,如果像素图像每次都显示非常高的情况,即使不模糊,你也可以检查另一个非常高的值。另一种方法可能是检测图片的焦点。

我正在做同样的事情。唯一的问题是,对于某些像素化模糊的图像,它显示出更高的值,而不是清晰的图像。 - Yashasvi Raj Pant
它们的差距很大吗?比如10000和1000? - Stian Diehard
并不是很多,但模糊的图像价值约为450左右,而清晰的图片价值约为250。 - Yashasvi Raj Pant
有进展吗?@YashasviRajPant 这只是我在研究后得出的一个想法:如果您模糊每张图片,然后编写算法进行再次检查,并将仍然显示高数字的那些图片放入类别==“像素”中怎么样? 我建议这样做的原因是因为Laplacian基本上检查图像中的正方形,因此像素图片始终会具有更高的数字! - Stian Diehard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接