用多边形绘制蒙娜丽莎

时间:2019-04-28 17:43:26

标签: python numpy matplotlib python-imaging-library genetic-algorithm

在用多边形绘制蒙娜丽莎时遇到问题,发生了什么事:

  • 几乎在第10,000代之后,一切看起来都是完全随机的。
  • 适应度值确实降低了,但是太慢了。

我找不到错误,我一直在尝试:

  • 更改参数
  • 更改突变

但是似乎没有任何作用。

这是我的代码:

import numpy as np
import random
from PIL import Image, ImageDraw
import matplotlib.pylab as plt
import copy


obj = Image.open('Mona.jpg').convert("RGBA")
obj_dimensions = (obj.width,obj.height)
obj_arr = np.asarray(obj)

OFFSET = 10
MIN = 3
MAX = 4

def generate_color():
    return tuple([random.randrange(0, 256) for k in range(4)])


class Population:

    def __init__(self,polygons,image):
        self.polygons = polygons
        self.image = image
        self.gen = 0

    def get_parent(self):
        polygon = random.choice(self.polygons)
        return polygon, self.polygons.index(polygon)                

    def start(self):
        self.redraw()
        fig, ax = plt.subplots(1,1)
        im = ax.imshow(obj)
        while True:
            plt.title("Gen: " + str(self.gen))

            parent, pos = self.get_parent()
            child = copy.deepcopy(parent)
            child.mutate()
            self.fitness(child,self.draw(child))
            self.crossover(parent,child,pos)

            im.set_data(self.image)
            print(abs(np.asarray(self.image) - obj_arr).sum())
            fig.canvas.draw_idle()
            plt.pause(0.0001)
            self.gen += 1

    @staticmethod
    def create(size):

        polygons = []
        image = Image.new('RGBA', obj_dimensions)

        for i in range(size):

            polygon = Polygon.create()
            draw = Population.draw(polygon)
            Population.fitness(polygon,draw)
            image = Image.alpha_composite(image, draw)
            polygons.append(polygon)

        return Population(polygons,image)

    @staticmethod
    def fitness(polygon,img):
        polygon.fitness = np.resize(abs(np.asarray(img) - obj_arr).sum(axis=(0,1)),3)

    def crossover(self,parent,child,pos):

        pimage = abs(np.asarray(self.image) - obj_arr).sum()
        self.polygons[pos] = child
        self.redraw()
        cimage = abs(np.asarray(self.image) - obj_arr).sum()

        if pimage < cimage:
            self.polygons[pos] = parent
            self.redraw()


    @staticmethod
    def draw(polygon):
        draw = Image.new('RGBA', obj_dimensions)
        pdraw = ImageDraw.Draw(draw)
        pdraw.polygon(polygon.points, fill=polygon.color)
        return draw

    def redraw(self):
        image = Image.new('RGBA', obj_dimensions)
        for polygon in self.polygons:
            image = Image.alpha_composite(image, self.draw(polygon))
        self.image = image



class Polygon:

    def __init__(self,points,color,fitness,changeable):
        self.points = points
        self.color = color
        self.fitness = fitness
        self.changeable = changeable

    @staticmethod
    def generate_points():
        sides = random.randint(MIN,MAX)
        points = []
        for i in range(sides):
            x = np.random.randint(0 - OFFSET, obj.width + OFFSET)
            y = np.random.randint(0 - OFFSET, obj.height + OFFSET)
            points.append((x,y))
        return points

    @staticmethod
    def create():

        points = Polygon.generate_points()

        return Polygon(points,(0,0,0,0),0,True)

    def mutate(self):
        if random.random() <= 0.5:
            self.color = generate_color()
            return False

        else:
            self.points = self.generate_points()
            return True

a = Population.create(50)
a.start()

0 个答案:

没有答案