我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python实现使用遗传算法进行图片拟合

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python实现使用遗传算法进行图片拟合

引言

算法思路

假设我们有这样一个生物族群,他们的每个基因片段都是一个个三角形(即只含三个点和颜色信息),他们每个个体表现出的性状就是若干个三角形叠加在一起。假设我们有一张图片可以作为这种生物族群最适应环境的性状,即长得越像这张图片的越能适应环境,越不像这张图片的越容易被淘汰。

当然作为一个正常的生物族群,他应该也会有正常的繁衍以产生新个体。产生新个体的过程中来自父亲和母亲的基因会进行交叉互换和变异,变异又可以有增加基因片段、减少基因片段以及不同位置的基因片段顺序互换。

但是一个族群不能够无限的繁殖,我们假设环境资源只能容纳有限的生物族群规模,所以我们在产生足够多的后代之后就要把他们放到族群里与族群内部进行竞争淘汰。这样一来,通过不断地淘汰,这个族群就会越来越像我们给定的图片。这就是算法的基本思路。

流程图

在这里插入图片描述

下面我们来看一下实现过程,为了方便解释,我们会结合python建立类似于伪代码的函数进行解释,不能直接运行,具体可运行的代码可直接下载参照最后的类封装的完整代码

预备知识及准备工作

打开图片

我们使用imageio中的imread打开图片,这里为了方便后续使用我们建立OpenImg函数,返回打开的图片img(格式为array),图片的格式(方便后期图片的保存),图片的大小:row和col(为后期画图做准备)。

from imageio import imread

def OpenImg(imgPath):
	img = imread(imgPath)
    row, col = img.shape[0], img.shape[1]
    return img, imgPath.split(".")[-1], row, col

随机生成生物族群

我们假设一个族群的最大生物个数为max_group,用groups来表示族群,g为族群内的生物个体,运用随机数随机产生个体。

from random import choice

for i in range(max_group):
	g = []
    for j in range(features):
	    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)))

    g.append(tmp.copy())
    groups.append(g.copy())

按照生物性状画图

我们使用PIL画图,首先我们建立一个空白的画布,然后再将个体的特征(三角形)画到图上。

from PIL import Image, 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_similarity

def 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 = 100
def 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 imread
from PIL import Image

imgPath = input("输入图片路径")
img = imread(imgPath)
img = img[::2, ::2, :]
img = Image.fromarray(img)
img.save(imgPath)

原图

我们以拟合一个小蓝鸟和一个心形为例来展示拟合过程

在这里插入图片描述
在这里插入图片描述

拟合过程展示

代码实现(这里已经事先将重复图片删除了)

import os
import 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 图片拟合内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python实现使用遗传算法进行图片拟合

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python如何实现使用遗传算法进行图片拟合

小编给大家分享一下python如何实现使用遗传算法进行图片拟合,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!引言算法思路假设我们有这样一个生物族群,他们的每个基因片段都是一个个三角形(即只含三个点和颜色信息),他们每个个体
2023-06-29

如何使用Python实现遗传算法

本篇内容介绍了“如何使用Python实现遗传算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!遗传算法是模仿自然界生物进化机制发展起来的随机
2023-07-05

使用Python实现遗传算法的完整代码

这篇文章主要介绍了使用Python实现遗传算法,其本质是一种高效、并行、全局搜索的方法,自适应的控制搜索过程以求得最优解,需要的朋友可以参考下
2023-03-23

如何使用Python实现图像融合及加法运算

这篇文章主要介绍“如何使用Python实现图像融合及加法运算”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何使用Python实现图像融合及加法运算”文章能帮助大家解决问题。一.图像加法运算1.Nu
2023-06-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录