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


当前回答

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

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

其他回答

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

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

基于耐克的答案。使用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方法,它有很高的假阳性率,在我的应用程序中是有用的。

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

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

编辑:

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

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

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