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


当前回答

这就是我在Opencv中检测区域焦点质量的方法:

Mat grad;
int scale = 1;
int delta = 0;
int ddepth = CV_8U;
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
/// Gradient X
Sobel(matFromSensor, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
/// Gradient Y
Sobel(matFromSensor, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
cv::Scalar mu, sigma;
cv::meanStdDev(grad, /* mean */ mu, /*stdev*/ sigma);
focusMeasure = mu.val[0] * mu.val[0];

其他回答

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

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

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).

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

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

编辑:

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

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

   1
1 -4  1
   1

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

谢谢妮基的拉普拉斯建议。 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,即使它完全模糊。

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

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

估计图像清晰度的另一种非常简单的方法是使用拉普拉斯(或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本质上是整个图像的平均值。函数的减少速度也更快,所以设置一个“模糊”阈值可能更容易。