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

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形