Python学习班微分享实录:用Python实现Mosaic Photo

2024-02-11 13:10

本文主要是介绍Python学习班微分享实录:用Python实现Mosaic Photo,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文基于CSDN Python学习班微分享内容整理,主要讲解了如何通过Python程序实现Mosaic Photo效果。主讲人陈舸,8年开发经验,曾就职华为、烽火通信,目前创业中。《Python Cookbook第三版》译者,《Linux/Unix系统编程手册 下卷》以及《算法精解 C语言描述》合作译者。点击这里下载程序源码

肯定有人会问什么是Mosaic Photo,那我们先来看一看最终的效果吧。

image

上图是在google上搜索的mosaic风格的图片。这种风格的图片都是由其它多张小图拼接而来的,最终形成了一张大图。我们可以在一些广告和海报上找到这种风格的设计。今天分享一个用Python写的程序,帮我们实现这种效果。

我们选了一张《越狱》的海报作为目标图片。最后我们会用多张图片拼接实现一张mosaic风格的海报,如下图所示。


我们可以在网上随机搜索100张图片作为拼接的素材。这些素材图不求高像素,但求随机。我们这次下载的素材图最大也不过几十KB。

首先,我们需要将目标图片分解为大小相等的block。同时,我们将素材图批量剪裁成与block大小相等的方形小图,在这里我们称之为tile。我们只要选取“合适”的tile像贴墙砖一样贴到block上,就可以得到最终的Mosaic海报了。

过程听起来很简单,但其中有两个核心问题:
1. 什么叫“合适”?
2. 怎么确定哪个tile贴到哪个block上?

先解决第一个问题。所谓“合适”,就是指我们选取的tile和要被贴的block在颜色上看起来最接近。目标图被划分成无数个block之后,有的区域颜色比较明亮,有的则偏暗,而我们手里的tile素材图更是五花八门,需要有一种方法能在众多的tile里选择出一个颜色与对应block最相近的,那这个“合适”与否也就可以确定了。

在对比颜色之前,我们先简单说明一下像素相关知识。

像素pixel,可简单看做(R,G,B)3维向量。因此要比对出颜色最接近的tile,其实就是去比对像素的差异。两个像素间的差异就是3维向量之间的距离,距离越小表示越接近也就越相似。那我们怎么求这个距离?

一维的求解:sqrt((x-y)^2) == | x – y|

二维的求解:sqrt((x1-x2)^2 + (y1-y2)^2)

三维的求解:sqrt((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2)

以此类推,我们可以将其扩展至n维。我们可以采用此方法,针对每个block,找到整体像素差异最小的那个tile,即为“合适”。

第二个问题,怎么知道哪个tile要贴到哪个block上?

当我们把原图划分成block后,其实每个block就有了一个坐标,用来确定这个block在目标图中的位置。而我们贴图用的资源tiles,可以全部读取到python的list中去,因此tile就有了下标索引。有了坐标,有了索引,就可以建立tile与block的对应关系。

到这里,我们已经解决了两个核心的问题。至于如何贴图、缩放、改变图片大小,我们就可以交给PIL库帮助我们解决。
大家在PIL库的网站可下载适用于Python 2.x 的PIL库,Python 3则可使用Pillow。

解题思路已经敲定,开始coding!

从上述代码可以看到,首先导入我们用的库,然后定义一些全局变量。

TILE_SIZE       = 3  

由于我们划分的block是 3x3 的大小,因此tile的大小也是 3x3 。

ENLARGEMENT     = 1  

第7行代码表示我们对目标图的放大倍数是1。如果设置成其他值,比如2,那么 300x200 的目标图,最后产生的结果将是 600x400。

EOQ_VALUE       = None

这个变量用来通知工作进程结束,我们在后面会详解。

下面开始编写class代码。

TileProcessor类就是用来处理我们的贴图素材tile的。init方法是接受传入的图片文件夹的路径。用get_tiles遍历目录中所有的图片,做一下裁剪后放入list。具体裁剪成方形的代码在22-27行。对于非正方形的tile,我们裁剪出正中心的方形区域作为备选的tile。

接下来我们看看TargetImage类,如下图代码所示。

TargetImage类用来处理我们的目标图,代码应该很好理解。在64行有一个if判断。因为我不希望贴图的时候出现最后还差半个或非整数个block,因此如果有这种情况,那我把原图也稍微做下裁剪,使得每行和每列要贴的block都是整数个。

如上图所示,在TileFilter这个类中,我们来确定哪个tile是“合适”的。其中,第84行的diff累加,就是之前我们说的计算3维向量的距离。get_best_fit_tile方法会返回最合适的那个tile所在的下标。此前,我们把所有tiles都裁剪为方形后存在list中。

如上图所示,MosaicImage类就是我们用来贴tile的类。初始化方法里我们根据目标图,按比例先生成一张底图,tile就是贴在这个底图之上。

除此之外,还有帮助类ProgressCounter,告诉我们贴图进度。在这里我们不赘述,大家可以下载源码查看,注释得很清楚。

接下来,我们还需要一些函数,将这些类串联起来。首先,我们来看compose函数。它非常关键,当我们拿到目标图的数据和tiles的数据后,就是调用它来完成后面的工作的,也就是合成拼图。

这里我们用了多进程,加速处理最佳tile匹配。可以看到,compose函数里起了几个新进程,有的用来处理tile匹配,有的用来贴图,通过队列queue来传递数据。因此,我们还写了一个 build_mosaic 函数(如下图所示),这个就是贴图进程所调用的函数。而最佳tile匹配就由 fit_tiles 函数(如下图所示)来完成。

最后,我们写一个main,让程序跑起来,我们看一下最终实现的效果。


希望加入Python 学习班?

请扫群主二维码,注明“Python”

这篇关于Python学习班微分享实录:用Python实现Mosaic Photo的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/699867

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount