比较两个BufferedImage之间像素值的最快方法是什么?

6

我有一个类型为TYPE_INT_BGR的BufferedImage。我需要逐像素比较另一个BufferedImage,以计算两个图像之间的“距离”。我有一些可以工作但速度较慢的代码。我从“参考”图像中获取像素,并使用以下方式将其拆分为RGB字节:

    int pixel = referenceImage.getRGB(col, row);
    int red   = (pixel >> 16) & 0xff;
    int green = (pixel >> 8) & 0xff;
    int blue  = (pixel) & 0xff;

我将比较r/g/b值与候选图像相应的像素,并求出差异的平方和。
有没有更快的方法来进行这种比较?查看JRE源代码,我发现BufferedImage.getRGB()实际上是将光栅中的组成RGB值进行OR运算,这对我的目的来说是浪费的,因为我只是再次将其分解为字节。
我将尝试直接进行操作,但我想知道是否有更好的方法来完成这个任务,无论是通过Java还是第三方API。
4个回答

3
从VolatileImage中读取数据并不会更快。使VolatileImage“更快”的是它们使用加速(VRAM)内存而不是系统(RAM)内存来绘制图像。然而,在进行读取时,可能需要访问另一个总线上的内存,并且对于这些操作,它比系统内存慢。
比较BufferedImage的最快方法是使用整数比较,就像您在帖子中讨论的那样,但是正如您提到的,由于性能原因,您不能使用getRGB。您可以将一批像素获取到一个数组中,但是总体而言,为了提高性能,您应该直接查看栅格和数据缓冲区。

你说得对,Volatile 不是一个好的建议。我已经将其删除了。不幸的是,我无法给自己的回答投反对票。 - Mikeb

2

如果两个图像使用相同的颜色模型和采样,你可以在光栅的DataBuffer上进行比较,这样会更快一些。


1
是的,这两个图像都使用相同的颜色模型和采样。假设使用DataBuffer时仍需要进行位移,但可能至少可以避免将值重新OR在一起。 - George Armhold
如果有帮助的话,我正在处理的所有图像都是“离屏”的;一个是从JPG中读取的,另一个是通过绘制到Graphics2D中构建的。我以前从未使用过VolatileImage,我会去了解一下。 - George Armhold

2

您是否考虑使用Java2D创建一个新图像,该图像是您拥有的两个图像之间的差异,然后分析差异图像呢?

我的初始方法是对图像A取反,并添加图像B。


这似乎是一个好主意,但我在寻找示例方面运气不佳。我猜我需要实现java.awt.CompositeContext。我看到的唯一实现是SunCompositeContext,不幸的是没有提供源代码。 - George Armhold

0
如果将字节拆分和加载额外类是问题所在,可以尝试以下方法:
从RGB像素值获取BufferedImage值
img = 65536*R + 256*G + B - 16777216;  

从 BufferedImage 值 img 获取 RGB 值

R=  Math.round((((371*img)+24576000000) / 96000000)
G=  Math.round((65536 + 0.003906*img - 256*R));
B=  Math.round((65536*R + 256*G -img - 16777216));

我不确定这是否是更好/更快的方法,但它是另一种替代方法,不使用任何额外的类,而是一个直接的数学过程(或黑客)...在某些情况下可能会有用(请仔细检查,因为这是我自己的方法,我没有足够的时间去尝试)。

我不知道你需要像素值之间的比较类型,所以这篇文章只讲到这里...希望有人真的会发现这有用!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接