颜色数量最少的政治地图

时间:2018-06-06 17:12:59

标签: java bufferedimage

我试图用最少数量的collors为政治地图上色。我现在尝试实现目标的方式是:

我用洪水算法填充地图上的空白区域。然后通过检查像素的颜色是否与白色和颜色列表中的颜色不同来检查是否到达边框。如果颜色不同,那么我将沿着与之前相同的方向进一步穿过像素,直到我从列表或白色到达像素颜色。当它是白色或列表但与当前颜色颜色不同时,我打破循环,当边框后面的颜色与当前颜色相同时,我再次使用列表中的下一个颜色填充国家/地区。 问题是我使用的地图通常有这样的边界: enter image description here

边框背后的像素并非真白。我的代码只是通过这些像素返回到它所来自的同一个国家/地区结果从列表中获取下一个颜色,然后在Out of bound异常中。 我该如何解决这个问题?我不想为我的代码创建特殊的地图,我希望它可以用于任何等高线图。

这是我的代码。这非常粗糙,因为我正在尝试不同的方法。所以任何建议都会受到影响:)

public class ImageColoring {

    private final int NORTH = 0;
    private final int SOUTH = 1;
    private final int WEST = 2;
    private final int EAST = 3;


    private final int[] COLORS = {-16726785,-65536,-15073025,-16711757,-16711919,-256,-417268,-455455,-5741663,-14194369,-14730152,-9885900};
    private List<Integer> colorList;

    private int colorCounter;
    private boolean shouldBreakRecursion = false;


    private BufferedImage image;

    public ImageColoring(BufferedImage image) {
        this.image = image;
        colorList = new ArrayList<>();
        for(int i = 0;i<COLORS.length;i++){
            colorList.add(COLORS[i]);
        }
    }

    public BufferedImage colorImage(){


        try{
            for (int i = 0; i < image.getWidth(); i++) {
                for (int j = 0; j < image.getHeight(); j++) {
                    if (image.getRGB(i, j) == -1) {
                        fill(i, j, EAST);
                        colorCounter = 1;
                        //incrementCounter();
                    }

                }
            }
        }catch (StackOverflowError e){

        }

        return image;
    }


    private void fill(int x, int y, int direction){
        if(x<0 || y<0 || x>=image.getWidth() || y>=image.getHeight() || shouldBreakRecursion){
            return;
        }
        //if(image.getRGB(x,y)!=-1) return;
        if(image.getRGB(x,y)!=-1 && !colorList.contains(image.getRGB(x,y))){
            if(direction == NORTH){
                for(int i = y-1;i>0;i--){
                    if(image.getRGB(x,i) == COLORS[colorCounter]){
                        colorCounter++;
                        fill(x,y+1,SOUTH);
                        return;
                    }
                    if(image.getRGB(x,i) == -1  || colorList.contains(image.getRGB(x,i))) return;
                }
            }else if(direction == SOUTH){
                for(int i = y+1;i<image.getHeight();i++){
                    if(image.getRGB(x,i) == COLORS[colorCounter]){
                        colorCounter++;
                        fill(x,y-1,NORTH);
                        return;
                    }
                    if(image.getRGB(x,i) == -1  || colorList.contains(image.getRGB(x,i))) return;

                }
            }else if(direction == EAST){
                for(int i = x+1;i<image.getWidth();i++){

                    if(image.getRGB(i,y) == COLORS[colorCounter]){
                        System.out.println(image.getRGB(i,y) +" : "+COLORS[colorCounter]);
                        colorCounter++;
                        fill(x-1,y,WEST);
                        return;
                    }
                    if(image.getRGB(i,y) == -1  || colorList.contains(image.getRGB(i,y))) return;
                }
            }else if(direction == WEST){
                for(int i = x-1;i>0;i--){
                    if(image.getRGB(i,y) == COLORS[colorCounter]){
                        colorCounter++;
                        fill(x+1,y,EAST);
                        return;
                    }
                    if(image.getRGB(i,y) == -1  || colorList.contains(image.getRGB(i,y))) return;
                }
            }
            return;
        }else if(image.getRGB(x,y)!=-1) return;
        image.setRGB(x,y,COLORS[colorCounter]);



        fill(x+1,y, EAST);
        //fill(x-1,y,WEST);
        fill(x,y-1,NORTH);
        fill(x,y+1,SOUTH);

    }

    private void incrementCounter(){
        if(++colorCounter == COLORS.length) colorCounter = 1;
    }
}