序:

        几年前,看到6H猎人在网上做的动态世界各国领土变化的视频,被深深的吸引了,那个视频也特别火,被各大知名媒体引入,本想向作者询问视频制作软件,却被告之是一帧帧画出来的,作为一个资深地图迷和程序员自然不能忍。其实看视频的时候就已经在想这些算法该怎么写了,后来偶然看到了一个网站,调出了他的JS代码,学习了一下,又结合各种因素想了想,基本所有问题都已经解决了,就差开始动手了。于是今天就开始解决第一个问题,分析出空白地图中的区域。搞了一天,最终完成了。在网上不知道是不是自己的关键字搜索的不正确,总是找不到好方法。于是自己想了这个愚钝的办法,结果挺满意。

 

零、过程总述:

    1、初步填充:这一步会首先一次将地图填充完毕,因为在自上而下用不同的颜色填充可能区域的时候,并不能准确知道那一部分和那一部分是一个区域,所以很容易出现一个区域多种颜色的情况。

    2、颜色归类:分析出哪些颜色是其实是一个颜色,将他们归类。

    3、最终填充:在依然像第一步一样遍历一遍图片,这次根据第二次的颜色归类,将属于同一区域的颜色,填充为同一种颜色。最终实现我们的目标

 

一、初步填充

             填充规则,每个格子如果上面符合填充规则的话(列入上格既不是边界,也不是水,而且格子存在)颜色等于上面,否则判断左侧格子。如果上和左都不符合,则随机一种颜色填充。很显然A1是是随机出的颜色。B1颜色从A1来,A2颜色也从A1来。到了H1则再次随机颜色。

 

 


                填充后会发现如下问题

 

     侧视图效果:

     

     我的效果颜色是因为,我的颜色并不是随机的,而是初始颜色为(0,0,0),每次换颜色就+1 (0,0,1)  蓝色满了就进一,以此类推。所以效果看起来又黑又蓝。其实只要不是同一区域内的绝对不是同一种颜色。只是颜色变化太小,人的眼睛分辨不出,之所以黑蓝交替出现,是因为出现了进位比如(0,1,0) 在人眼睛里依然是黑色。如果地图很大,则会看到绿色逐步出现。过度感很强。

      也许你会发现,很多区域都别细长条所填充。并不是我们想要的样子。接下来我们需要进入第二步,颜色归类。

二、颜色归类

 

        虽然说是第二步,其实我们可以在第一步中进行,当我们对G3颜色进行判断后,虽然确定了G3的颜色,可是不需要那么快结束,接着判断一下他的左边是否为合法相邻块。如果是,那么就查看一下颜色是否和自己相同,如果不同,则他两个是属于同一区域的不同颜色,将这两种颜色归为一类。

三、最终填充

        最后一步,最后一次遍历地图,将属于同一区域的颜色,填充为为同一颜色。就得到了效果。

代码如下

from PIL import Image 
import random
#im = Image.open('./org-s.bmp')
im = Image.open('./org.bmp')


def isVaildColor(color):
    return color!=(102,102,102) and color!=(153,204,255)

def randMapColor():
    color=(random.randint(0,255),random.randint(0,255),random.randint(0,255))
    while(not isVaildColor(color)):
        color=(random.randint(0,255),random.randint(0,255),random.randint(0,255))
    return color

def findAncestors(colFather):
    while(colorFatherDir[colFather]!=colFather):
        #print("不是祖元素,下一个!",colFather)
        colFather=colorFatherDir[colFather]
    return colFather


def MapColorP(color):
    r=color[0]
    g=color[1]
    b=color[2]+1
    if b>255:
        b=0
        g=g+1
        if g>255:
            g=0
            r=r+1
            print("红色进位")
            if r>255:
                print("颜色不够用")
                r=0
    color=(r,g,b)

    if isVaildColor(color):
        return color
    else:
        return MapColorP(color,1)

print("-------------------------------处理中----------------------------------")

color=(0,0,0)
color=MapColorP(color)

colorFatherDir={}
colorFatherDir[color]=color
for i in range(im.size[0]):
    if isVaildColor(im.getpixel((i,0))):
        im.putpixel((i,0),color)
    else:
        color=MapColorP(color)
        colorFatherDir[color]=color

for j in range(1,im.size[1]):
    if isVaildColor(im.getpixel((0,j))):
        if isVaildColor(im.getpixel((0,j-1))):
            colorMate=im.getpixel((0,j-1))
            im.putpixel((0,j),colorMate)
        else:
            color=MapColorP(color)
            colorFatherDir[color]=color
            im.putpixel((0,j),color)
    for i in range(1,im.size[0]):
        if isVaildColor(im.getpixel((i,j))):
            if isVaildColor(im.getpixel((i,j-1))):
                colorMate=im.getpixel((i,j-1))
                im.putpixel((i,j),colorMate)
                #归属集处理
                if isVaildColor(im.getpixel((i-1,j))):
                    if findAncestors(im.getpixel((i,j)))!=findAncestors(im.getpixel((i-1,j))):
                        colorFatherDir[findAncestors(im.getpixel((i,j)))]=findAncestors(im.getpixel((i-1,j)))
            elif isVaildColor(im.getpixel((i-1,j))):
                colorMate=im.getpixel((i-1,j))
                im.putpixel((i,j),colorMate)
            else:
                color=MapColorP(color)
                colorFatherDir[color]=color
                im.putpixel((i,j),color)

print("颜色总数",len(colorFatherDir))
realColor={}
for father in colorFatherDir:
    realColor[findAncestors(father)]=randMapColor()

for j in range(1,im.size[1]):
    for i in range(1,im.size[0]):
        if isVaildColor(im.getpixel((i,j))):
            colFather=im.getpixel((i,j))
            im.putpixel((i,j),realColor[findAncestors(colFather)])
            

im.show()
im.save("./tmp.bmp","BMP") #保存图像为gif格式




我这张图的边界颜色为(102,102,102),水的颜色为(153,204,255)

如果自己手里有待填充地图,请改为适合自己的颜色。