2013-06-25 4 views
0

Я строю алгоритм заполнения залипа, который, надеюсь, в конце концов найдет лицо в центре фотографии, основанное на цвете в точном центре, и подобные им цвета. Однако на данный момент мой алгоритм должен принимать любой цвет в пределах массива int и передавать его в массив держателей, в основном создавая копию исходного изображения. Но это не работает и приводит к черному изображению, когда я запускаю его. Может ли кто-нибудь увидеть проблему, которую мне не хватает?Flood Fill Algorithm Resulting in Black Изображение

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

}

+0

Самая большая проблема с использованием рекурсивного алгоритма заливку. Хотя это будет работать на небольших изображениях, это, безусловно, не получится для изображений с умеренным или большим размером. Я бы предложил использовать подход к алгоритму сканирования. См. *** [это] (http://en.wikipedia.org/wiki/Flood_fill) *** для получения дополнительной информации. –

ответ

0

Вы создаете ИНТ [] [] называется заполнены, а затем вызвать заливку (...), который возвращает ничего не делая для массива. image.length всегда равна высоте и изображению [0]. длина всегда равна ширине, поэтому она всегда возвращается из второго оператора if.

Затем вы создаете BufferedImage из этого пустого массива и записываете его в файл. Все значения в массиве инициализируются до 0, что дает вам черный цвет.

Изменение цикла for в findFace (..) на нижеследующее позволит сохранить исходное изображение из массива держателя.

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

Но я не уверен, что это то, о чем вы просите или нет.

Edit: Попробуйте это и посмотреть, если он посылает вас в правильном направлении:

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

О, ты совершенно прав о втором случае. Я не знаю, почему я написал это, он должен проверять положение x и y, чтобы убедиться, что они не находятся за пределами границ. Теперь я получаю ошибку ArrayIndexOutOfBoundsException, но это шаг вперед. Благодаря! – user2506643

+0

Я отредактирую выше, чтобы включить метод, который ... вроде работает. Сейчас у меня нет времени для расследования, но этого может быть достаточно, чтобы вы начали. – MaxAlexander

+0

Святая крада, спасибо за помощь. Это работает очень хорошо. Я ценю это. – user2506643