图像模糊的简单指标?

时间:2013-07-11 00:31:19

标签: java image image-processing

我试图判断某张照片是否模糊。我知道这基本上是一项不可能完成的任务,并且任何指标有时会返回不良结果。

我想知道是否有一个简单的指标至少试图估计我可以使用的模糊。具体而言,该任务具有对误报的高容忍度。例如如果我得到的东西可以消除90%的模糊照片和50%的非模糊照片,我会非常高兴。

我正在尝试用Java实现它。我有一个像素数组(作为整数)。请记住,我对图像处理技术(傅立叶变换等)的理解有限,我希望能够对如何编写解决方案进行非常具体的演练。

3 个答案:

答案 0 :(得分:2)

正如您所说,您不会找到通用指标。

还有不同类型的模糊:均匀,各向异性,运动模糊......

通常,模糊图像往往表现出低频。可能的描述符是k个最高频率的幅度之和。总和较低的图像可能会模糊不清。

使用傅立叶频谱(高频远离原点)或Laplace pyramid(高频对应于第一音阶),可以在N * log(N)时间内获得幅度。

Wavelet transform是另一个可能的描述符

答案 1 :(得分:2)

一个非常简单的措施是应用Sobel滤波器并研究滤波图像的整体能量。图像越模糊,边缘消失越多,滤波图像的能量越小。当你试图确定模糊和不模糊的阈值时,你会遇到这种方法的问题,但也许这个简单的方法会给你一个想法。

检查维基百科的Sobel过滤器,这是一个代码片段,用于获取图像的边缘比率。您可以使用这些边缘比率来配对比较图像是否具有更多或更少的边缘。不过,请记住,这是一个简单的方法,a.lasram的答案肯定是正确的。

    float[] sobelX = {
            -1, 0, 1,
            -2, 0, 2,
            -1, 0, 1,
    };
    BufferedImage image = ImageIO.read(new File("test.jpg"));
    ColorConvertOp grayScaleOp = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
    BufferedImage grayImage = grayScaleOp.filter(image, null);
    BufferedImageOp op = new ConvolveOp( new Kernel(3, 3, sobelX) );
    BufferedImage result = op.filter(grayImage, null);
    WritableRaster r = result.getRaster();
    int[] pixel = new int[r.getWidth()];
    double countEdgePixels = 0;
    for (int y = 0; y<r.getHeight();y++) {
        // System.out.println("y = " + y);
        r.getPixels(0, y, r.getWidth(),1, pixel);
        for (int i = 0; i < pixel.length; i++) {
            // create some stat out of the energy ...
            if (pixel[i] > 128) {
                countEdgePixels++;
            }
        }
    }
    System.out.printf("Edge pixel ratio = %4.4f\n", countEdgePixels/(double) (r.getWidth()*r.getHeight()));
    ImageIO.write(result, "png", new File("out.png"));

答案 2 :(得分:1)

有点迟到的回复但值得下一个会碰到这个问题的人。

我在谷歌学者中发现了一些论文,这些论文讨论了将图片中所有边缘的总和与所有边缘的宽度相比较的平均值,这可以在这两篇文章中看到:First和{{3} }。