我想知道是否有一种方法可以通过分析图像数据来确定图像是否模糊。


当前回答

我在matlab中使用FFT实现了它,并检查FFT的直方图,计算平均值和STD,还可以做拟合函数

fa =  abs(fftshift(fft(sharp_img)));
fb = abs(fftshift(fft(blured_img)));

f1=20*log10(0.001+fa);
f2=20*log10(0.001+fb);

figure,imagesc(f1);title('org')
figure,imagesc(f2);title('blur')

figure,hist(f1(:),100);title('org')
figure,hist(f2(:),100);title('blur')

mf1=mean(f1(:));
mf2=mean(f2(:));

mfd1=median(f1(:));
mfd2=median(f2(:));

sf1=std(f1(:));
sf2=std(f2(:));

其他回答

我目前使用的一种方法是测量图像中边缘的分布。请看这篇论文:

@ARTICLE{Marziliano04perceptualblur,
    author = {Pina Marziliano and Frederic Dufaux and Stefan Winkler and Touradj Ebrahimi},
    title = {Perceptual blur and ringing metrics: Application to JPEG2000,” Signal Process},
    journal = {Image Commun},
    year = {2004},
    pages = {163--172} }

它通常都是付费版本,但我也看到过一些免费版本。基本上,他们在图像中定位垂直边缘,然后测量这些边缘的宽度。平均宽度给出了图像的最终模糊估计结果。较宽的边缘对应模糊的图像,反之亦然。

该问题属于无参考图像质量估计领域。如果你在谷歌Scholar上查一下,你会得到很多有用的参考资料。

EDIT

下面是nickie发布的5张图片的模糊估计图。数值越高,模糊程度越高。我使用固定大小的11x11高斯滤波器,并改变了标准偏差(使用imagemagick的convert命令来获得模糊的图像)。

如果你比较不同大小的图像,不要忘记通过图像宽度归一化,因为较大的图像会有更宽的边缘。

最后,一个重要的问题是区分艺术模糊和不必要的模糊(由对焦缺失、压缩、拍摄对象相对于相机的运动引起),但这超出了像这样简单的方法。举个艺术模糊的例子,看看莱娜的形象:莱娜在镜子里的倒影是模糊的,但她的脸是完美的聚焦。这有助于对莱纳图像进行更高的模糊估计。

谢谢妮基的拉普拉斯建议。 OpenCV文档给我指出了同样的方向: 使用python, cv2 (opencv 2.4.10)和numpy…

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
numpy.max(cv2.convertScaleAbs(cv2.Laplacian(gray, 3)))

结果在0-255之间。我发现任何超过200的东西都非常清晰,而到了100,就明显模糊了。Max从来没有真正低于20,即使它完全模糊。

是的,它是。计算快速傅里叶变换并分析结果。傅里叶变换告诉你图像中出现了哪些频率。如果有少量的高频,那么图像是模糊的。

定义术语“低”和“高”取决于你。

编辑:

正如评论中所述,如果你想用一个浮点数来表示给定图像的模糊度,你必须计算出一个合适的度量。

尼基的回答提供了这样一个衡量标准。将图像与拉普拉斯核进行卷积:

   1
1 -4  1
   1

并且在输出上使用一个健壮的最大度量来获得一个可以用于阈值的数字。在计算拉普拉斯函数之前尽量避免平滑过多的图像,因为你只会发现平滑后的图像确实是模糊的:-)。

我想到了一个完全不同的解决方案。 我需要分析视频静止帧,以便在每(X)帧中找到最清晰的帧。这样,我将检测运动模糊和/或失焦图像。

我最终使用了Canny边缘检测,我得到了非常非常好的结果,几乎每一种视频(与尼基的方法,我有数字化的VHS视频和沉重的交错视频的问题)。

我通过在原始图像上设置感兴趣区域(ROI)来优化性能。

使用EmguCV:

//Convert image using Canny
using (Image<Gray, byte> imgCanny = imgOrig.Canny(225, 175))
{
    //Count the number of pixel representing an edge
    int nCountCanny = imgCanny.CountNonzero()[0];

    //Compute a sharpness grade:
    //< 1.5 = blurred, in movement
    //de 1.5 à 6 = acceptable
    //> 6 =stable, sharp
    double dSharpness = (nCountCanny * 1000.0 / (imgCanny.Cols * imgCanny.Rows));
}

在这篇文章中,我尝试了基于拉普拉斯滤波器的解决方案。这对我没有帮助。所以,我尝试了这篇文章中的解决方案,它对我的情况很好(但很慢):

import cv2

image = cv2.imread("test.jpeg")
height, width = image.shape[:2]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

def px(x, y):
    return int(gray[y, x])

sum = 0
for x in range(width-1):
    for y in range(height):
        sum += abs(px(x, y) - px(x+1, y))

较少模糊的图像具有最大和值!

你也可以通过改变步长来调整速度和准确度。

这部分

for x in range(width - 1):

你可以用这个替换

for x in range(0, width - 1, 10):