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


当前回答

估计图像清晰度的另一种非常简单的方法是使用拉普拉斯(或LoG)滤波器,并简单地选择最大值。如果你期待噪音,使用像99.9%分位数这样的稳健测量可能会更好(即选择第n高的对比度而不是最高的对比度)。如果你希望图像亮度变化,你还应该包括一个预处理步骤来标准化图像亮度/对比度(例如直方图均衡化)。

我已经在Mathematica中实现了Simon的建议,并在一些测试图像上进行了尝试:

第一个测试使用不同内核大小的高斯滤波器模糊测试图像,然后计算模糊图像的FFT,并取90%最高频率的平均值:

testFft[img_] := Table[
  (
   blurred = GaussianFilter[img, r];
   fft = Fourier[ImageData[blurred]];
   {w, h} = Dimensions[fft];
   windowSize = Round[w/2.1];
   Mean[Flatten[(Abs[
       fft[[w/2 - windowSize ;; w/2 + windowSize, 
         h/2 - windowSize ;; h/2 + windowSize]]])]]
   ), {r, 0, 10, 0.5}]

得到对数图:

5条线代表5张测试图像,X轴代表高斯滤波半径。图像是递减的,因此FFT是一个很好的度量清晰度的方法。

这是“最高LoG”模糊估计器的代码:它简单地应用一个LoG过滤器,并返回过滤结果中最亮的像素:

testLaplacian[img_] := Table[
  (
   blurred = GaussianFilter[img, r];
   Max[Flatten[ImageData[LaplacianGaussianFilter[blurred, 1]]]];
   ), {r, 0, 10, 0.5}]

得到对数图:

这里未模糊图像的传播稍微好一点(2.5 vs 3.3),主要是因为这种方法只使用图像中最强的对比度,而FFT本质上是整个图像的平均值。函数的减少速度也更快,所以设置一个“模糊”阈值可能更容易。

其他回答

基于耐克的答案。使用opencv实现基于拉普拉斯的方法很简单:

short GetSharpness(char* data, unsigned int width, unsigned int height)
{
    // assumes that your image is already in planner yuv or 8 bit greyscale
    IplImage* in = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
    IplImage* out = cvCreateImage(cvSize(width,height),IPL_DEPTH_16S,1);
    memcpy(in->imageData,data,width*height);

    // aperture size of 1 corresponds to the correct matrix
    cvLaplace(in, out, 1);

    short maxLap = -32767;
    short* imgData = (short*)out->imageData;
    for(int i =0;i<(out->imageSize/2);i++)
    {
        if(imgData[i] > maxLap) maxLap = imgData[i];
    }

    cvReleaseImage(&in);
    cvReleaseImage(&out);
    return maxLap;
}

将返回一个短消息,指示检测到的最大锐度,根据我对真实世界样本的测试,这是一个很好的指标,说明相机是否对焦。不足为奇的是,正常值是依赖于场景的,但远不如FFT方法,它有很高的假阳性率,在我的应用程序中是有用的。

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

@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命令来获得模糊的图像)。

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

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

上面的回答阐明了许多事情,但我认为做一个概念上的区分是有用的。

如果你对一个模糊的图像拍摄一张完美对焦的照片呢?

The blurring detection problem is only well posed when you have a reference. If you need to design, e.g., an auto-focus system, you compare a sequence of images taken with different degrees of blurring, or smoothing, and you try to find the point of minimum blurring within this set. I other words you need to cross reference the various images using one of the techniques illustrated above (basically--with various possible levels of refinement in the approach--looking for the one image with the highest high-frequency content).

我在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(:));

在高度重视的期刊(IEEE Transactions on Image Processing)上发表的两种方法的Matlab代码可在这里获得:https://ivulab.asu.edu/software

检查CPBDM和JNBM算法。如果你检查代码,它并不难移植,顺便说一下,它是基于Marzialiano的方法作为基本特征。