我正在使用以下循环来计算相同大小的两幅图像之间的差异:
static double calculateError(BufferedImage canvas, BufferedImage ideal) {
double error = 0.0D;
for (int x = 0; x < Polygonizer.WIDTH; x++) {
for (int y = 0; y < Polygonizer.HEIGHT; y++) {
Color c1 = new Color(canvas.getRGB(x, y));
Color c2 = new Color(ideal.getRGB(x, y));
error += Math.abs(c1.getRed() - c2.getRed());
error += Math.abs(c1.getGreen() - c2.getGreen());
error += Math.abs(c1.getBlue() - c2.getBlue());
}
}
return error;
}
它工作正常,但速度很慢,而且我不知道如何使其更快。
我已经尝试过使用ExecutorService
不好,我可以使用一些建议。
编辑:谢谢大家。这是优化的版本:
private static int APPROXIMATION = 1;
private static int[] idealData;
public static final void setIdeal(BufferedImage ideal) {
int[] rawData = ((DataBufferInt)ideal.getRaster().getDataBuffer()).getData();
idealData = new int[rawData.length * 3];
int counter = 0;
for (int i = 0; i < rawData.length * 3; i += 3) {
idealData[i] = (rawData[counter] & 0xFF);
idealData[i + 1] = (rawData[counter] >> 8 & 0xFF);
idealData[i + 2] = (rawData[counter] >> 16 & 0xFF);
counter++;
}
}
static double calculateError(BufferedImage canvas) {
long error = 0;
final int[] canvasData = ((DataBufferInt)canvas.getRaster().getDataBuffer()).getData();
int counter = 0;
for (int i = 0; i < canvasData.length; i += APPROXIMATION) {
error += Math.abs((canvasData[i] & 0xFF) - (idealData[counter]));
error += Math.abs((canvasData[i] >> 8 & 0xFF) - (idealData[counter + 1]));
error += Math.abs((canvasData[i] >> 16 & 0xFF) - (idealData[counter + 2]));
counter += 3 * APPROXIMATION;
}
return error;
}
答案 0 :(得分:2)
如果您知道BufferedImage
的格式(例如,因为您使用构造函数实例化了它们),那么还有一种更快的方法。
如果BufferedImage
的类型为TYPE_3BYTE_BGR
,请执行以下操作:
byte[] canvasData = ((DataBufferByte)canvas.getRaster().getDataBuffer()).getData();
byte[] idealData = ((DataBufferByte)ideal .getRaster().getDataBuffer()).getData();
int error = 0;
for (int i = 0; i < canvasData.length; i++) {
error += Math.abs((canvasData[i] & 0xFF) - (idealData[i] & 0xFF));
}
如果BufferedImage
的类型为TYPE_INT_RGB
,请执行以下操作:
int[] canvasData = ((DataBufferInt)canvas.getRaster().getDataBuffer()).getData();
int[] idealData = ((DataBufferInt)ideal .getRaster().getDataBuffer()).getData();
int error = 0;
for (int i = 0; i < canvasData.length; i++) {
error += Math.abs((canvasData[i] & 0xFF) - (idealData[i] & 0xFF));
error += Math.abs((canvasData[i] >> 8 & 0xFF) - (idealData[i] >> 8 & 0xFF));
error += Math.abs((canvasData[i] >> 16 & 0xFF) - (idealData[i] >> 16 & 0xFF));
}
(免责声明:未经测试的代码,但是我经常做的事情足以使我确信)
答案 1 :(得分:1)
您可以为每个点创建两个renderPlot
实例,这很多。从int提取RGB的方法要快得多(请查看Color
的来源)。
更重要的是,您一点一点地提取点,这通常非常慢(因为它们在Color
中的组织方式可能不同)。调用一次将更多的提取到BufferedImage
中的方法。
AFAIK有一种让图像计算结果的方法,它可能仍然更快。
我已经尝试过使用
int[]
不好,我真的可以使用一些建议。
这也应该有所帮助,但仅取决于您拥有的内核数。但是,使用并行流通常要简单得多。但这是一个不同的故事(问题)。