索贝尔过滤器很奇怪

时间:2016-09-05 15:09:10

标签: java bufferedimage sobel

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

我的第一件事是拿起输入图像的某些点。我想尝试Sobel进行检测,我已阅读soble article

现在我遇到了一些我不知道如何实施sobel过滤器的问题。我的尝试是:

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

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

然后 - &gt;计算每个点的梯度

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

最后 - &gt;使用上面的渐变

创建新图像
 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:

现在我明白了:

为什么这么黑?

1 个答案:

答案 0 :(得分: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元素类型),以便减少量化输出。