8

の各ピクセルのRGB値を取得する最速の方法は何BufferedImageですか?

現在、以下のコードに示すように2つのループを使用してRGB値をfor取得していますが、ネストされたループが画像に対して合計479999回実行されるため、これらの値を取得するのに時間がかかりすぎました。16ビット画像を使用すると、この数値はさらに高くなります。

ピクセル値を取得するためのより高速な方法が必要です。

これが私が現在使用しようとしているコードです:

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg"));

int countloop=0;  

for (int x = 0; x <bi.getWidth(); x++) {
    for (int y = 0; y < bi.getHeight(); y++) {
        Color c = new Color(bi.getRGB(x, y));
        System.out.println("red=="+c.getRed()+" green=="+c.getGreen()+"    blue=="+c.getBlue()+"  countloop="+countloop++);                                                                                                                                                  
    }
}
4

5 に答える 5

15

これが役立つかどうかはわかりません。まだテストしていませんが、次の方法でrgb値を取得できます。

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg"));
int[] pixel;

for (int y = 0; y < bi.getHeight(); y++) {
    for (int x = 0; x < bi.getWidth(); x++) {
        pixel = bi.getRaster().getPixel(x, y, new int[3]);
        System.out.println(pixel[0] + " - " + pixel[1] + " - " + pixel[2] + " - " + (bi.getWidth() * y + x));
    }
}

ご覧のとおり、ループ内で新しい色を初期化する必要はありません。また、onemasseが提案するように、幅/高さのループを反転して、すでに持っているデータからカウンターを取得しました。

于 2012-04-10T12:42:54.623 に答える
7

多数の個別のgetRGBから1つの大きなgetRGBに変更して、画像全体を配列にコピーすることにより、実行時間は33,000ミリ秒から3,200ミリ秒に大幅に短縮されましたが、配列の作成時間はわずか31ミリ秒でした。

間違いなく、配列への1回の大きな読み取りと配列の直接インデックス付けは、多くの個別の読み取りよりもはるかに高速です。

パフォーマンスの違いは、クラスの最後でのブレークポイントステートメントの使用に関連して表示されます。ブレークポイントがループの外側にある間、クラス内のコードのすべての行がブレークポイントについてテストされているように見えます。個別のgetに変更しても、速度は向上しません。

コードはまだ正しいので、答えの残りの部分はまだ役立つかもしれません。

古い読み取りステートメント

colorRed=new Color(bi.getRGB(x,y)).getRed();

ビットイメージを配列にコピーするための読み取りステートメント

int[] rgbData = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), 
                null, 0,bi.getWidth());        

getRGBを配列に入れると、3つの色の値すべてが1つの配列要素に入れられるため、回転して「and」を付けることにより、個々の色を抽出する必要があります。y座標に画像の幅を掛ける必要があります。

配列から個々の色を読み取るためのコード

colorRed=(rgbData[(y*bi.getWidth())+x] >> 16) & 0xFF; 

colorGreen=(rgbData[(y*bi.getWidth())+x] >> 8) & 0xFF; 

colorBlue=(rgbData[(y*bi.getWidth())+x]) & 0xFF; 
于 2012-11-28T04:23:10.617 に答える
2

外側のループの行と内側の列をループする必要があります。そうすれば、キャッシュミスを回避できます。

于 2012-04-10T12:25:11.997 に答える
2

BufferedImage.getRGB(int、int、int、int、int []、int、int)を試しましたか?

何かのようなもの:

int[] rgb = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth() * bi.getHeight(), bi.getWidth()])

試していなかったので、速いかどうかわかりません。

編集 @コードを見たので、おそらくそうではありませんが、一見の価値があります。

于 2012-04-10T12:20:21.900 に答える
0

ここで解決策を見つけました https://alvinalexander.com/blog/post/java/getting-rgb-values-for-each-pixel-in-image-using-java-bufferedi

BufferedImage bi = ImageIO.read(new File("C:\\images\\Sunset.jpg"));

for (int x = 0; x < bi.getWidth(); x++) {
    for (int y = 0; y < bi.getHeight(); y++) {
        int pixel = bi.getRGB(x, y);
        int red = (pixel >> 16) & 0xff;
        int green = (pixel >> 8) & 0xff;
        int blue = (pixel) & 0xff;
        System.out.println("red: " + red + ", green: " + green + ", blue: " + blue);                                                                                                                                                  
    }
}
于 2018-01-08T14:03:21.550 に答える