Java 改进直方图
我用这个方法来获取一幅图像的像素值,我用它来比较一幅图像和50幅其他图像。然而,产生产出需要永远的时间。有人知道我有什么办法可以加速这个方法吗?将图像转换为灰度会更快吗?如果有人能帮助编写代码,那就太好了Java 改进直方图,java,image-processing,histogram,grayscale,Java,Image Processing,Histogram,Grayscale,我用这个方法来获取一幅图像的像素值,我用它来比较一幅图像和50幅其他图像。然而,产生产出需要永远的时间。有人知道我有什么办法可以加速这个方法吗?将图像转换为灰度会更快吗?如果有人能帮助编写代码,那就太好了 public static double[] GetHistogram (BufferedImage img) { double[] myHistogram = new double [16777216]; for (int y = 0; y < img.getHei
public static double[] GetHistogram (BufferedImage img) {
double[] myHistogram = new double [16777216];
for (int y = 0; y < img.getHeight(); y += 1)
{
for (int x = 0; x < img.getWidth(); x += 1)
{
int clr = img.getRGB(x,y);
Color c = new Color(img.getRGB(x, y));
int pixelIntValue = (int) c.getBlue() * 65536 + c.getGreen() * 256 + c.getRed();
myHistogram[pixelIntValue]++;
}
}
return myHistogram;
}
publicstaticdouble[]GetHistogram(BufferedImage-img){
double[]myHistogram=新的双精度[16777216];
对于(int y=0;y
计算包含16777216个类的直方图是非常不寻常的。
大多数直方图是针对每个通道分别计算的,结果是R、G和B各有一个256级直方图。如果将图像转换为灰度,则只有一个直方图
我不是Java方面的专家。我不知道编译器优化代码有多聪明。
但是您可以为图像的每一行调用img.getHeight(),为每一列调用img.getWidth()。
我不知道这些表达式实际计算的频率,但是如果在开始循环之前只使用两个变量来指定图像的宽度和高度,可能可以节省一些处理时间
还可以为每个像素调用img.getRGB(x,y)两次。同样的故事。也许只做一次比较快。函数调用通常比从内存中读取变量慢
你也应该想想你在这里做什么。getRGB(x,y)为颜色提供整数表示。
然后你把这个整数放进一个控制器,从中生成一个彩色对象。然后使用c.getBlue()等从该颜色对象中获取红色、绿色和蓝色的整数值。再把它组合成一个整数
您可以直接使用getRGB的返回值,并至少保存4个函数调用、3个乘法、3个求和
因此,再次考虑到我上一次编程Java,就像10年前一样,我的函数看起来更像:
public static double[] GetHistogram (BufferedImage img) {
double[] myHistogram = new double [16777216];
int width = img.getWidth()
int height = img.getHeight()
for (int y = 0; y < height; y += 1)
{
for (int x = 0; x < width; x += 1)
{
int clr = img.getRGB(x,y);
myHistogram[clr]++;
}
}
return myHistogram;
publicstaticdouble[]GetHistogram(BufferedImage-img){
double[]myHistogram=新的双精度[16777216];
int width=img.getWidth()
int height=img.getHeight()
对于(int y=0;y
}
当然,数组的类型和大小是不正确的,整个16777216类直方图没有意义,但这可能有助于加快速度。
我只需要使用一个位掩码从整数中获取红色、绿色和蓝色值,并创建三个直方图。TLDR:使用较小的图像并阅读纸张 您应该尽量消除@Piege提到的任何不必要的函数调用,但您肯定应该将颜色保留在一个直方图中,而不是R、G和B的单独直方图中。除了去掉额外的函数调用,我认为可以做四件事来加速算法的创建和比较直方图,并减少内存使用(因为页面缓存越少,磁盘抖动越少,速度越快)
使用较小的图像 颜色直方图索引的优点之一是它相对独立于分辨率。对象的颜色不随图像的大小而改变。显然,这一设想存在局限性,即尝试使用1×1图像匹配对象。但是,如果你的图像有数百万像素(像现在大多数智能手机的图像一样),你肯定应该调整它的大小。这些作者发现,只有16×11的图像分辨率仍然可以产生非常好的结果[],但即使将分辨率调整到~100×100像素,也应该可以提供显著的速度提升 从
图像
继承该方法,您可以使用该方法获得较小的图像
double scalingFactor = 0.25; //You need to choose this value to work with your images
int aSmallHeight = myBigImage.getHeight() * scalingFactor;
int aSmallWidth = myBigImage.getWidth() * scalingFactor;
Image smallerImage = myBigImage.getScaledInstance(aSmallWidth, aSmallHeight, SCALE_FAST);
减小图像大小是加快算法速度最有效的方法。如果你什么都不做,至少要这样做
使用来自每个颜色通道的较少信息 这不会对生成直方图产生太大的影响,因为它实际上需要更多的计算,但会显著加快直方图的比较。总的想法叫做。基本上,如果红色值在0..255范围内,它们可以表示为一个字节。在该字节中,某些位比其他位更重要 考虑这个颜色示例图像。我在左上角放置了一个几乎任意的红色阴影,在其他每个角落,我忽略了红色通道中的一个或多个位(由颜色字节中的下划线表示)。我故意选择了一种有很多一个位的颜色,这样我就可以显示忽略一个位的“最坏”情况。(当我们忽略零位时,“最佳”情况对颜色没有影响。) 右上角和左上角没有太大区别,尽管我们忽略了一点。左上角和左下角有一个可见的,但最小的差异,即使我们忽略了3位。左上角和右下角非常不同,尽管我们只忽略了一个位,因为它是最重要的位。通过策略性地忽略不太重要的位,您可以减小直方图的大小,这意味着JVM移动的空间更小,在比较它们时的存储箱也更少 这里有一些实数。目前,您有28×28×28=16777216个箱子。如果忽略每个颜色通道中的3个最低有效位,您将得到 25×25×25=32768个料仓,为料仓数量的1/512
int numBits = 3;
int quantizedRed = pixelColor.getRed() >> numBits;
int quantizedGreen = pixelColor.getGreen() >> numBits;
int quantizedBlue = pixelColor.getBlue() >> numBits;
byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();