1

最近、私は次のLow Polyような準備をしています:

私の最初のことは、入力画像のいくつかのポイントをピックアップすることです。Sobel検出を試みたいので、 soble articleを読みました。

今、私はsobelフィルターを実装する方法がわからないという問題に遭遇しました.Followingは私の試みです:

まず -> 入力画像からグレイデータを取得

 try {
        mImage = ImageIO.read(new File("D:\\Documents\\Pictures\\engine.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    mWidth = mImage.getWidth();
    mHeight = mImage.getHeight();
    mNewImage = new BufferedImage(mWidth, mHeight, mImage.getType());
    mGrayData = new int[mWidth * mHeight];
    // get pixel data from image
    for (int i = 0; i < mHeight; i++) {
        for (int j = 0; j < mWidth; j++) {
            int rgb = mImage.getRGB(j, i);
            int r = (rgb >> 16) & 0xff;
            int g = (rgb >> 8) & 0xff;
            int b = rgb & 0xff;
            int grayLevel = (r + g + b) / 3;
            mGrayData[i * mWidth + j] = grayLevel;
        }
    }

次に->すべてのポイントの勾配を計算します

  private int[] getGradient() {
    int[] gradient = new int[mWidth * mHeight];
    for (int x=1;x<mWidth-1;x++){
        for (int y=1;y<mHeight-1;y++){
            int grayX = getGrayPoint(x+1,y-1)+2*getGrayPoint(x+1,y)+getGrayPoint(x+1,y+1)-
                    (getGrayPoint(x-1,y-1)+2*getGrayPoint(x-1,y)+getGrayPoint(x-1,y+1));
            int grayY = (getGrayPoint(x-1, y+1) + 2*getGrayPoint(x,y+1)+getGrayPoint(x+1,y+1))-
                    (getGrayPoint(x-1,y-1) + 2*getGrayPoint(x,y-1) + getGrayPoint(x+1,y-1));
            gradient[x+y*mWidth] = (int) Math.sqrt(grayX*grayX+grayY*grayY);
        }
    }
    return gradient;
}

最後 - >上記のグラデーションで新しい画像を作成します

 private void createImage() {
    int[] gradient = getGradient();

    for (int y = 1; y < mHeight - 1; ++y)
        for (int x = 1; x < mWidth - 1; ++x)
            mNewImage.setRGB(x,y,gradient[y * mWidth + x]);

    File file = new File("D:\\Documents\\Pictures\\engine3.png");
    if (!file.exists()) {
        file.getParentFile().mkdir();
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        ImageIO.write(mNewImage, "png", file);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

元の画像

それはどのように見えるべきですか?

私が得たもの

色が少し青いのが不思議

編集1:

今私は得る:

なぜそんなに黒いのですか?

4

1 に答える 1

2

ここで色を設定します。

mNewImage.setRGB(x,y,gradient[y * mWidth + x]);

赤、緑、青のチャンネルの値が同じであることを確認するために何もしていません。

整数の 32 ビットは、アルファ、赤、緑、青を表す 4 つの 8 ビット チャネルをパックするために使用されます。

0x01234567 = overall color

  01       = alpha
    23     = red
      45   = green
        67 = blue

単一の値のみを設定しています。これは 0 から 255 の範囲外にはないように見えるため、効果的に青チャネルのビットのみを設定しています。(おそらく、ARGB ではなく RGB カラー モデルも使用しているため、ピクセルが完全に透明ではありません)。

3 つのチャネルを同じ値に設定します (値を 0 ~ 255 の間にクランプして、誤って他のチャネルのビットを設定しないようにします)。

int gray = Math.max(0, Math.min(gradient[...], 255);
int color = (0xff << 24) | (gray << 16) | (gray << 8) | (gray);
          // Alpha         Red            Green         Blue

最大勾配を持つポイントにグレー値 255 が割り当てられるように、勾配値をスケーリングすることもできることに注意してください。

int maxGradient = 0;
for (int g : gradient) { 
  maxGradient = Math.max(maxGradient, g);
}

それから:

int gray = Math.max(0, gradient) * 255 / maxGradient;

(最大で 255 になるようにクランプする必要はなくなりました)。

また、量子化された出力が少なくなるように、勾配配列float[]or double[](および に同じ要素タイプを使用) を作成することもできます。maxGradient

于 2016-09-05T15:16:54.827 に答える