黑色图像的洪水填充算法

时间:2013-06-25 16:12:18

标签: java recursion colors flood-fill

我正在构建一个洪水填充算法,希望最终能够根据精确中心的颜色和周围相似的颜色在照片中心找到一张脸。然而,目前,我的算法应该在int数组的范围内采用任何颜色并将其转移到持有者数组,实质上是制作原始图像的副本。但是这不起作用,并且当我运行它时会导致黑色图像。任何人都可以看到我错过的问题吗?

public class TemplateMaker {

public static void main(String[] args) throws IOException {
    importPhoto();
}

public static void importPhoto() throws IOException {
    File imgPath = new File("/Pictures/BaseImage.JPG");
    BufferedImage bufferedImage = ImageIO.read(imgPath);
    establishArray(bufferedImage);
}

public static void establishArray(BufferedImage bufferedImage) throws IOException {
    //byte[] pixels = hugeImage.getData();
    int width = bufferedImage.getWidth();
    System.out.println(width);
    int height = bufferedImage.getHeight();
    System.out.println(height);
    int[][] result = new int[height][width];
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++) {
            result[i][j] = bufferedImage.getRGB(j, i);
        }
    findFace(result);
}

public static void findFace(int[][] image) throws IOException {
    int height = image.length;
    int width = image[0].length;
    Color centerStart = new Color(image[height / 2][width / 2], true);
    System.out.println(centerStart.getRGB());
    System.out.println(Color.blue.getRGB());

    int[][] filled = new int[height][width];

    floodFill(height / 2, width / 2, centerStart, image, filled, height, width);

    //construct the filled array as image.
    BufferedImage bufferImage2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            bufferImage2.setRGB(y, x, filled[x][y]);
        }
    }
    //save filled array as image file
    File outputfile = new File("/Pictures/saved.jpg");
    ImageIO.write(bufferImage2, "jpg", outputfile);
}

public static int[][] floodFill(int x, int y, Color targetColor, int[][] image, int[][] filled, int height, int width) {

    //execute something similar once algorithm works. 
    // if (image[x][y] < targetColor.getRGB()/2 || image[x][y] > targetColor.getRGB()*2) return filled;

    if (image[x][y] == Color.blue.getRGB()) {
        return filled;
    }
    if (image.length < 0 || image[0].length < 0 || image.length >= height || image[0].length >= width) {
        return filled;
    }
    filled[x][y] = image[x][y];
    image[x][y] = Color.blue.getRGB();

    floodFill(x - 1, y, targetColor, image, filled, height, width);
    floodFill(x + 1, y, targetColor, image, filled, height, width);
    floodFill(x, y - 1, targetColor, image, filled, height, width);
    floodFill(x, y + 1, targetColor, image, filled, height, width);
    return filled;
}

}

1 个答案:

答案 0 :(得分:0)

你创建名为 filled 的int [] [],然后调用floodFill(...),它返回而不对数组做任何事情。 image.length总是等于height,而image [0] .length总是等于width,所以它总是从第二个if语句返回。

然后从该空白数组构建BufferedImage并将其写入文件。数组中的所有值都初始化为0,这使您变黑。

将findFace(..)中的for循环更改为以下内容将保存您的holder数组中的原始图像。

        for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            bufferImage2.setRGB(y, x, image[x][y]);
        }
    }

但我不确定这是不是你问的问题。

编辑:尝试一下,看看它是否向您发送了正确的方向:

    public static int[][] floodFill(int x, int y, Color targetColor, int[][] image, int[][] filled, int height, int width) {

    //execute something similar once algorithm works. 
    // if (image[x][y] < targetColor.getRGB()/2 || image[x][y] > targetColor.getRGB()*2) return filled;

    if (image[x][y] == Color.blue.getRGB()) {
        System.out.println("returned if 1");
        return filled;
    }
    /*if (image.length < 0 || image[0].length < 0 || image.length >= height || image[0].length >= width) {
        return filled;
    }*/
    filled[x][y] = image[x][y];
    image[x][y] = Color.blue.getRGB();

    if (x - 1 <= 0 && y < width) {
        floodFill(x - 1, y, targetColor, image, filled, height, width);
    }

    if(x + 1 < height && y >= 0 && y < width) {
        floodFill(x + 1, y, targetColor, image, filled, height, width);
    }

    if(x >= 0 && x < height && y - 1 <= 0) {
        floodFill(x, y - 1, targetColor, image, filled, height, width);
    }

    if(x >= 0 && x < height && y + 1 < width) {
        floodFill(x, y + 1, targetColor, image, filled, height, width);
    }

    return filled;
}