索贝尔过滤器很奇怪

Sobel filter is strange

最近我正在准备Low Poly这样的:

我的第一件事是提取输入的一些点image.I想尝试Sobel进行检测并且我已经阅读soble article

现在我遇到了不知道如何实现 sobel 的问题 filter.Folowing 是我的尝试:

首先->从输入图像中获取灰度数据

 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:

现在我得到:

为什么这么黑

你在这里设置颜色:

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

您没有采取任何措施来确保红色、绿色和蓝色通道中的值相同。

整数的32位用来打包4个8位通道,分别代表alpha、红、绿、蓝。

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 使用相同的元素类型),以便获得较少的量化输出。