遗传算法图像实验
遗传算法是什么?
所谓遗传算法,一种受达尔文自然进化理论启发的搜索启发式算法。主要包括了交叉繁殖,变异,自然选择这几个部分。
实验思路
本次的实验是利用遗传算法,重现一张图片。我们在这个实验中将图片看作是一个在自然选择下不断进化的一种生物。首先给定一张图片,这张图片就是我们要重现的图片,把它就看作是自然条件下最适合生存的类型,也就是经过自然选择最容易存货下来的类型。
程序运行,首先生成几张随机的图片,看作是这个生物的初代种。然后让这些图片经过交配遗传得到新的图片,再选出与给定的图片相似度更高的留下继续遗传,经过越来越多得遗传之后,子孙中的图片会与一开始给定得图片越来越像。
在这个实验中我们把图片的的每个像素点的rgb值看作图片遗传的基因。自然选择的方法就是把不断生成的图片的基因与给定的图片的基因进行比较,然后留下相似度最高的然后在进行繁殖。
遗传方法包括基因复制,即父代得基因原封不动得遗传给子代。交叉遗传,即来自父母双方得基因通过基因交叉得到得子代。基因突变,即将父代的基因做一些随机的改变在遗传给子代。
例如,给定得图像是
这是第2750代:
好像有点像目标的图片了。
接下来进行实验
实验的代码如下:
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 20 10:08:31 2020
@author: Administrator
"""
from PIL import Image
import os
import math
import random
import pickle
from copy import deepcopy
# 读取图像
def GetImage(ori_img):
img = Image.open(ori_img)
color = []
width, height = img.size
for j in range(height):
temp = []
for i in range(width):
r, g, b = img.getpixel((i, j))[:3]
temp.append([r, g, b, r+g+b])
color.append(temp)
return color, img.size
# 初始化
def RandGenes(size):
width, height = size
genes = []
for i in range(100):
gene = []
for j in range(height):
temp = []
for i in range(width):
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
temp.append([r, g, b, r+g+b])
gene.append(temp)
genes.append([gene, 0])
return genes
# 计算适应度
# 为了方便,定义的并不规范,谨慎参考
def CalcFitness(genes, target):
total = 0
for k, gene in enumerate(genes):
count = 0
for i, row in enumerate(gene[0]):
for j, col in enumerate(row):
t_r, t_g, t_b, t_a = target[i][j]
r, g, b, a = col
diff = abs(t_a - a)
count += (abs(t_r-r) + abs(t_g-g) + abs(t_b-b)) * diff
genes[k][1] = count
total += count
avg_total = total / (k+1)
for k, gene in enumerate(genes):
genes[k][1] = genes[k][1] / avg_total
genes.sort(key = lambda x: x[1])
return genes
# 变异
def Variation(genes):
rate = 0.5
for k, gene in enumerate(genes):
for i, row in enumerate(gene[0]):
for j, col in enumerate(row):
if random.random() < rate:
a = [-1, 1][random.randint(0, 1)] <