Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 改进直方图_Java_Image Processing_Histogram_Grayscale - Fatal编程技术网

Java 改进直方图

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

我用这个方法来获取一幅图像的像素值,我用它来比较一幅图像和50幅其他图像。然而,产生产出需要永远的时间。有人知道我有什么办法可以加速这个方法吗?将图像转换为灰度会更快吗?如果有人能帮助编写代码,那就太好了

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();