更快地从图像中提取直方图

时间:2011-11-21 20:25:01

标签: java image histogram

我正在寻找一种从图像中提取直方图数据的更快方法。 我目前正在使用这段代码,对于6mpx JPEG图像需要大约1200ms:

        ImageReader imageReader = (ImageReader) iter.next();
        imageReader.setInput(is);
        BufferedImage image = imageReader.read(0);
        int height = image.getHeight();
        int width = image.getWidth();
        Raster raster = image.getRaster();
        int[][] bins = new int[3][256];

        for (int i = 0; i < width; i++) 
            for (int j = 0; j < height; j++) {
                bins[0][raster.getSample(i, j, 0)]++;
                bins[1][raster.getSample(i, j, 1)]++;
                bins[2][raster.getSample(i, j, 2)]++;

            }

你有什么建议吗?

2 个答案:

答案 0 :(得分:6)

您正在进行很多 getSamples 方法调用,他们会轮流拨打电话和电话等。

我经常使用图片和 获得速度的典型技巧是直接操作底层 int [] (在这种情况下,你的BufferedImage必须由int支持[])。

访问 int [] 和执行 getRGB 之间的区别可能是巨大的。当我写巨大的时候,我的意思是两个数量级(尝试在OS X 10.4和 int [x] 上做 getRGB ,你会看到性能增益)。

此外, getSamples 没有三次通话。我只是检索一个对应于你的ARGB像素的int然后用bitshift来获得RGB波段(你每个R,G和B组件做一个直方图吗?)。

您可以通过以下操作访问像素阵列:

final int[] a = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

此外,您可以使用单个循环执行您想要的操作,循环遍历所有像素。

而不是:

for ( int x = 0; x < width; x++ ) {
    for ( int y = 0; y < height; y++ ) {
        ....

你可以这样做:

for ( int p = 0; p < width*height; p++ ) {

现在,如果你想进行更奇怪的优化,那么你可能不会那么有效:

  • 使用循环展开(迭代超过600万像素是可能有帮助的极少数情况之一)

  • 反转循环:for(p = width * height - 1; p&gt; = 0; p - )

答案 1 :(得分:1)

你可以使用getSamples(int x,int y,int w,int h,int b,double [] dArray)方法 这种方法可能有内部优化。 此外,您可以尝试交换宽度和高度。

for (int i = 0; i < width; i++) 
   for (int j = 0; j < height; j++) {
   }
}

并且

for (int i = 0; i < height; i++) 
   for (int j = 0; j < width; j++) {
   }
}

在这两种变体之间,性能差异将是巨大的。 这是cpu缓存的影响