У меня проблема с прорисовкой Моны Лизы полигонами, происходит следующее:
- после почти 10000-го поколения все выглядит совершенно случайно.
- значение пригодности снижается, но слишком медленно.
Я не могу найти ошибку, я пытался:
- изменить параметры
- изменить мутации
Но, похоже, ничего не работает.
Вот мой код:
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()