我正在寻找一种从图像中提取直方图数据的更快方法。 我目前正在使用这段代码,对于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)]++;
}
你有什么建议吗?
答案 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缓存的影响