1

Recently I am preparing for Low Poly like this:

My first thing is to pick up some points of the input image.I want to try Sobel for detection and I have read soble article.

Now I meet problem where I don't know how to implement sobel filter.Folowing is my try:

First -> Get gray data from input image

 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;
        }
    }

Then -> Calculate gradient of every point

  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;
}

Last -> Create new image with above 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();
    }
}

Original image

What it should look like?

What I got

It's so strange that the color is a little blue

Edit 1:

Now I get:

why is it so black?

4

1 回答 1

2

您在此处设置颜色:

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

您没有做任何事情来确保红色、绿色和蓝色通道中的值相同。

整数的 32 位用于打包 4 个 8 位通道,分别代表 alpha、red、green 和 blue。

0x01234567 = overall color

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

您只设置一个值;这看起来不超出 0 到 255 的范围,因此您实际上只是在蓝色通道中设置位。(大概您还使用了 RGB 颜色模型,而不是 ARGB,这就是像素不完全透明的原因)。

将三个通道设置为相同的值(并将值限制在 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[]double[](并为 使用相同的元素类型maxGradient),以便获得更少的量化输出。

于 2016-09-05T15:16:54.827 回答