1

Java に組み込まれている畳み込み演算子を使用する代わりに、独自の畳み込み演算子を作成しようとしています。この画像リンクに組み込みの畳み込み演算子を適用しました

組み込みの畳み込み演算子とガウス フィルターを使用して、この画像を取得しました。 リンク

今、コードを使用して同じ画像を実行します

public static int convolve(BufferedImage a,int x,int y){
 int red=0,green=0,blue=0;
      float[] matrix = { 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 0.2196956447338621f, 0.28209479177387814f, 0.2196956447338621f, 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 };
      for(int i = x;i<x+3;i++){
          for(int j = y;j<y+3;j++){
              int color = a.getRGB(i,j);
              red += Math.round(((color >> 16) & 0xff)*matrix[(i-x)*3+j-y]);
              green += Math.round(((color >> 8) & 0xff)*matrix[(i-x)*3+j-y]);
              blue += Math.round(((color >> 0) & 0xff)*matrix[(i-x)*3+j-y]);

          }
      }

    return (a.getRGB(x, y)&0xFF000000) | (red << 16) | (green << 8) | (blue);
}

で、得た結果がこれです。 リンク

また、私が書いたコードを最適化するにはどうすればよいですか。組み込みの畳み込み演算子は 1 ~ 2 秒かかりますが、コードが想定どおりに正確な目的を果たしていない場合でも、5 ~ 7 秒かかります。

アップロード中にソース画像を誤って回転させてしまいました。だから無視してください。

4

1 に答える 1

1

まず第一に、ループの各サイクルで不必要に (そして間違って) 結果を float から int に変換しています。あなたのred, greenandblueは float 型である必要があり、畳み込みの後でのみ整数にキャストする必要があります (RGB に変換された場合):

  float red=0.0f, green = 0.0f, blue = 0.0f
  for(int i = x;i<x+3;i++){
      for(int j = y;j<y+3;j++){
          int color = a.getRGB(i,j);
          red += ((color >> 16) & 0xff)*matrix[(i-x)*3+j-y];
          green += ((color >> 8) & 0xff)*matrix[(i-x)*3+j-y];
          blue += ((color >> 0) & 0xff)*matrix[(i-x)*3+j-y];

      }
  }

return (a.getRGB(x, y)&0xFF000000) | (((int)red) << 16) | (((int)green) << 8) | ((int)blue);

matrix結果の色のにじみは、係数が間違っているために発生します。

0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f +
0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f +
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f =

1.8452741

ぼかし畳み込み行列の係数の合計は 1.0 である必要があります。このマトリックスを画像に適用すると、255 を超える色が得られる場合があります。その場合、チャネルは次のチャネルに「流れ込み」ます (青から緑など)。このマトリックスを使用した完全に緑色の画像は、次のようになります。

緑 = 255 * 1.8452741 ~= 471 = 0x01D7;
 rgb = 0xFF01D700;

これは、赤が少し入った、あまり強くない緑です。

係数を で割ることで修正できますが、次の1.8452741ことを確認する必要があります。

(int)(255.0f * (係数の合計)) = 255

そうでない場合は、チャネルのサイズを 255 に制限するチェックを追加し、それらをラップアラウンドさせないようにする必要があります。例えば:

if (red > 255.0f)
   red = 255.0f;

効率/最適化について:
速度の違いは、この不必要なキャストと Math.Round の呼び出しによって説明される可能性がありますが、より可能性の高い候補は、画像にアクセスする方法です。私は BufferedImage と Raster に精通しておらず、基になる画像バッファーにアクセスする最も効率的な方法についてアドバイスすることができません。

于 2013-11-10T11:18:29.277 に答える