python图像融合算法,遗传算法图像
最近项目需要图像拟合。本文主要介绍利用遗传算法进行图像拟合的python实现。通过示例代码详细介绍,具有一定的参考价值。感兴趣的朋友可以参考一下。
00-1010简介:前期知识和准备工作。打开图片,随机生成生物群。根据生物特征画图,比较生物个体与目标图片的相似性。保存图片。算法:主体交叉交换、基因突变、基因片段易位、增加基因片段变异、繁殖和淘汰。拟合实例显示了图像分辨率的降低。原图试衣过程展示完整代码下载(打包成类)
目录
算法思路
假设我们有这样一个生物群体,他们的每个基因片段都是一个三角形(即只包含三个点和颜色信息),每个基因片段所显示的性状都是几个三角形的叠加。假设我们有一张图,可以作为这个生物群体适应性最强的特质,就是越像这张图,越能适应环境,越不像这张图,越容易被淘汰。
当然,作为一个正常的生物群体,他也应该有正常的繁殖产生新的个体。在产生一个新个体的过程中,来自父亲和母亲的基因会发生交叉交换和突变,这种突变可以包括增加基因片段、减少基因片段、在序列中不同位置交换基因片段。
但是,一个群体不可能无限繁衍下去。我们假设环境资源只能容纳有限的生物群体规模,那么在产生足够多的后代后,我们就要把它们放入群体中,与群体竞争淘汰。这样通过不断的淘汰,这个族群会越来越像我们给定的画面。这是算法的基本思想。
流程图
我们来看看实现过程。为了解释方便,我们将结合python建立一个类似伪代码的函数进行解释,这个函数不能直接运行。具体的可运行代码可以参考最后一个类封装的完整代码直接下载。
引言
预备知识及准备工作
我们在imageio中使用imread打开图片。这里为了方便后续使用,我们设置了OpenImg函数,该函数返回打开的图片Img(数组格式),图片的格式(为了方便后期保存图片),图片的大小:row和col(为后期绘制做准备)。
从imageio导入imread
def打开(imgPath):
img=imread(imgPath)
row,col=img.shape[0],img.shape[1]
返回img,imgPath.split( . )[-1],行,列
打开图片
我们假设一个群体中生物的最大数量是max_group,用群体来代表群体,g是群体中的生物个体,用随机数来随机产生个体。
从随机导入选择
对于范围内的I(最大组):
g=[]
对于范围内的j(特性):
tmp=[[choice(np.linspace(0,row,features)),choice(np.linspace(0,col,features))] for x in range(3)]
tmp.append(# )。join(范围(6)中x的choice(0123456789ABCDEF ))
g.append(tmp.copy())
groups.append(g.copy())
随机生成生物族群
我们用PIL画画。首先,我们构建一个空白画布,然后我们在图片上绘制各个特征(三角形)。
从PIL进口图片,
ImageDraw
def to_image(g):
array = np.ndarray((img.shape[0], img.shape[1], img.shape[2]), np.uint8)
array[:, :, 0] = 255
array[:, :, 1] = 255
array[:, :, 2] = 255
newIm1 = Image.fromarray(array)
draw = ImageDraw.Draw(newIm1)
for d in g:
draw.polygon((d[0][0], d[0][1], d[1][0], d[1][1], d[2][0], d[2][1]), d[3])
return newIm1
对比生物个体和目标图片的相似度
使用structural_similarity对比两个图片的相似度,此时两个图片都应该是array类型
from skimage.metrics import structural_similaritydef getSimilar(g) -> float:
newIm1 = to_image(g)
ssim = structural_similarity(np.array(img), np.array(newIm1), multichannel=True)
return ssim
保存图片
调用我们之前建立好的to_image函数先将个体转换成图片,然后将图片保存即可。
def draw_image(g, cur, imgtype):image1 = to_image(g)
image1.save(os.path.join(str(cur) + "." + imgtype))
算法主体
交叉互换
考虑到后期的基因片段的增添和减少,所以应该分为两步,其一是相重合的位置进行交叉互换,以及对于多出来的尾部进行交叉互换,我们按照随机率random_rate和重合位置长度min_locate来确定交换的位数。然后我们使用sample选出若干位置进行互换。交换结束后再对尾部进行互换
random_rate = random()def exchange(father, mother)->[]:
# 交换
# 随机生成互换个数
min_locate = min(len(father), len(mother))
n = randint(0, int(random_rate * min_locate))
# 随机选出多个位置
selected = sample(range(0, min_locate), n)
# 交换内部
for s in selected:
father[s], mother[s] = mother[s], father[s]
# 交换尾部
locat = randint(0, min_locate)
fhead = father[:locat].copy()
mhead = mother[:locat].copy()
ftail = father[locat:].copy()
mtail = mother[locat:].copy()
# print(fhead, ftail, mhead, mtail)
fhead.extend(mtail)
father = fhead
mhead.extend(ftail)
mother = mhead
return [father, mother]
基因突变
随机选择的原理和目的与上面类似,这里我们把重新生成某个基因片段的信息看作基因突变。
random_rate = random()def mutation(gen):
# 突变
# 随机生成变异个数
n = int(randint(1, 100) / 1000 * len(gen))
selected = sample(range(0, len(gen)), n)
for s in selected:
tmp = [[choice(np.linspace(0, row, 100)), choice(np.linspace(0, col, 100))] for x in range(3)]
tmp.append("#" + .join(choice(0123456789ABCDEF) for x in range(6)))
gen[s] = tmp
return gen
基因片段易位
在个体的基因组内随机选择基因片段进行位置互换。
def move(gen):# 易位
exchage = int(randint(1, 100) / 1000 * len(gen))
for e in range(exchage):
sec1 = randint(0, len(gen) - 1)
sec2 = randint(0, len(gen) - 1)
gen[sec1], gen[sec2] = gen[sec2], gen[sec1]
return gen
增加基因片段
直接在个体基因组后面添加随机产生的基因片段即可。
features = 100def add(gen):
# 增加
n = int(randint(1, 100) / 1000 * len(gen))
for s in range(n):
tmp = [[choice(np.linspace(0, row,features)),choice(np.linspace(0, col, features))] for x in range(3)]
tmp.append("#" + .join(choice(0123456789ABCDEF) for x in range(6)))
gen.append(tmp)
return gen
减少基因片段
随机减少个体的若干基因片段
def cut(self, gen):# 减少
n = int(randint(1, 100) / 1000 * len(gen))
selected = sample(range(0, len(gen)), n)
g = []
for gp in range(len(gen)):
if gp not in selected:
g.append(gen[gp])
return g
变异
以此调用以上的突变、易位、增添和减少产生4种状态的基因片段
def variation(gen):# 变异
gen = mutation(gen.copy())
gen1 = move(gen.copy())
gen2 = add(gen1.copy())
gen3 = cut(gen2.copy())
return [gen, gen1, gen2, gen3]
繁殖
繁殖过程包括交叉互换和变异,直接调用之前构造的函数即可
def breeds(father, mother):new1, new2 = exchange(father.copy(), mother.copy())
# 变异
new3, new4, new5, new6 = variation(father.copy())
new7, new8, new9, new10 = variation(mother.copy())
return [new1, new2, new3, new4, new5, new6, new7, new8, new9, new10]
淘汰
建立个体和其与目标的相似度相关的映射关系,并按照相似度排序,然后去除相似度较低的个体,直到剩余生物个体的数量为max_group为止。在这个函数中我们还返回了一个最优个体的相似度来方便监测。
def eliminated(groups):group_dict = dict()
for gp in range(len(groups)):
group_dict[gp] = getSimilar(groups[gp])
group_dict = {key: value for key, value in sorted(group_dict.items(), key=lambda item: item[1], reverse=True)}
g = []
for key in list(group_dict.keys())[:max_group]:
g.append(groups[key].copy())
groups = g.copy()
return groups, list(group_dict.values())[0]
拟合
拟合过程先要进行若干次的繁殖,为了保证每次繁殖的个体数我们规定其至少选择最大个体数的一半数量的次数进行繁殖,繁殖之后的个体加入到种群当作和之前种群中的个体一起进行淘汰。通过这个过程我们每次淘汰都会将与目标差距最大的个体淘汰。
def breeds(father, mother):new1, new2 = exchange(father.copy(), mother.copy())
# 变异
new3, new4, new5, new6 = variation(father.copy())
new7, new8, new9, new10 = variation(mother.copy())
return [new1, new2, new3, new4, new5, new6, new7, new8, new9, new10]
示例展示
拟合时建议选择分辨率低的图片,如果选择的图片分辨率较高,可以使用以下代码降低图片分辨率
降低图片分辨率
from imageio import imreadfrom PIL import Image
imgPath = input("输入图片路径")
img = imread(imgPath)
img = img[::2, ::2, :]
img = Image.fromarray(img)
img.save(imgPath)
原图
我们以拟合一个小蓝鸟和一个心形为例来展示拟合过程
拟合过程展示
代码实现(这里已经事先将重复图片删除了)
import osimport math
import matplotlib.pyplot as plt
import matplotlib.image as image
path = "./xl"
length = len(os.listdir(path))
row = col = math.ceil(math.sqrt(length))
x = 1
lst = []
for d in os.listdir(path):
lst.append(int(d.split(.)[0]))
lst = sorted(lst)
for l in lst:
img = image.imread(os.path.join(path, str(l)+.png))
plt.xticks([])
plt.yticks([])
plt.subplot(row, col, x)
plt.imshow(img)
plt.xticks([])
plt.yticks([])
plt.title(str(l))
x += 1
plt.savefig(path)
plt.show()
效果
完整代码下载(已封装成类)
GitHub下载地址(推荐):
https://github.com/AiXing-w/Python-Intelligent-Optimization-Algorithms
到此这篇关于python实现使用遗传算法进行图片拟合的文章就介绍到这了,更多相关python 图片拟合内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。