【Python 项目】照片马赛克 - 1

照片马赛克 - 1

照片马赛克是一张图像,它被分割成长方形的网格,每个长方形由另一张匹配"目标"的图像(最终希望出现在照片马赛克中的图像)替代。换言之,如果从远处看照片马赛克,会看到目标图像;但如果走近,会看到该图像实际上包含许多较小的图像。这个迷题有解是因为人眼的工作方式。下图中的低分辨率块状图像,靠近了很难识别,但如果从远处看,就知道它代表什么,因为看到的细节较少,就使得边缘越光滑。照片马赛克的原理是相似的。从远处看,图像看起来正常,但走近时,秘密揭开了:每"块"都是一个独特的图像!

开始

本项目中,我们将学习如何用 Python 创建照片马赛克。我们将目标图像划分成较小图像的网格,并用适当的图像替换网格中的每一小块,创建原始图像的照片马赛克。你可以指定网格的尺寸,并选择输入图像是否可以在马赛克中重复使用。

在这个项目中,你将学习如何做到以下几点:

  • 用 Python 图像库(PIL)创建图像;
  • 计算图像的平均 RGB 值;
  • 剪切图像;
  • 通过粘贴另一张图像来替代原图像的一部分;
  • 利用平均距离测量来比较 RGB 值。

工作原理

要创建照片马赛克,就从目标图像的块状低分辨率版本开始(因为在高分辨率的图像中,小块图像的数量会太大)。该图像的分辨率将决定马赛克的维度 M×N(M 是行数,N 是列数)。接着,根据这种方法替换原始图像中的每一小块:

  1. 读入一些小块图像,它们将取代原始图像中的小块;
  2. 读入目标图像,将它分割成 M×N 的小块网格;
  3. 对于每个小块,从输入的小块图像中找到最佳匹配;
  4. 将选择的输入图像安排在 M×N 的网格中,创建最终的照片马赛克。

分割目标图像

按照下图中的方案,开始将目标图像划分成 M×N 的网格。

图像展示了如何将原始图像分割成小块的网格。 x 轴表示网格的列,y 轴表示网格的行。

现在,看看如何计算网格中一个小块的坐标。下标为(i,j)的小块,左上角坐标为 (iw, ij),右下角坐标为((i+1)*w, (j+1)*h),其中 w 和 h 分别是小块的宽度和高度。PIL 可以用这些数据,从原图像创建小块。

平均颜色值

图像中的每个像素都有颜色,由它的红、绿、蓝值来表示。在这个例子中,使用 8 位的图像,因此每个部分有 8 位值,范围在[0,255]。如果一幅图像共有 N 个像素,平均 RGB 计算如下:
r , g , b { r 1 + r 2 + . . . + r n N , g 1 + g 2 + . . . + g n N , b 1 + b 2 + . . . + b n N } r,g,b \left\{\begin{aligned} \end{aligned} \right.\frac{r_1+r_2+...+r_n} {N}, \frac{g_1+g_2+...+g_n}{N}, \frac{b_1+b_2+...+b_n}{N}\left.\begin{aligned} \end{aligned}\right\} r,g,b{Nr1+r2+...+rn,Ng1+g2+...+gn,Nb1+b2+...+bn}

请注意,平均 RGB 也是一个三元组,不是标量或一个数字,因为平均值是针对每个颜色成分分别计算的。计算平均 RGB 是为了匹配图像小块和目标图像。

匹配图像

对于目标图像中的每个小块,需要在用户指定的输入文件夹的一些图像中,找到一幅匹配的图像。要确定两个图像是否匹配,就使用平均 RGB 值。最接近的匹配就是最接近平均 RGB 值的图像。

要做到这一点,最简单的方法是计算一个像素中 RGB 值之间的距离,以便从输入图像中找到最佳匹配。对于几何中的三维点,可以用以下的距离计算方法:
D 1 , 2 = ( r 1 − r 2 ) 2 + ( g 1 − g 2 ) 2 + ( b 1 − b 2 ) 2 D_1,_2 = \sqrt { (r_1 - r_2)^2 + (g_1 - g_2)^2 + (b_1 - b_2)^2 } D1,2=(r1−r2)2+(g1−g2)2+(b1−b2)2

这里计算了点 (r1, g1, b1) 和 (r2, g2, b2) 之间的距离。给定一个目标图像的平均RGB 值,以及来自输入图像的平均 RGB 值列表,你可以使用线性搜索和三维点的距离计算,来找到最匹配的图像。

所需模块

这个项目将使用 Pillow 读入图像,访问其底层数据,创建和修改图像。还会用numpy 来操作图像数据。

相关推荐
坚持就完事了19 小时前
Java泛型
java·开发语言
X54先生(人文科技)19 小时前
启蒙灯塔起源团预言—碳硅智能时代到来
人工智能·python·机器学习·语言模型
Channing Lewis19 小时前
zoho crm的子表添加行时,有一个勾选字段,如何让它在details页面新建子表行(点击add row)时默认是勾选的
开发语言·前端·javascript
Miqiuha19 小时前
工作答辩框架
java·开发语言
happymaker062619 小时前
Java学习日记——DAY25(JavaSE完结)
java·开发语言·学习
qq_242188633220 小时前
快速搭建跨环境检测服务的步骤
linux·开发语言·windows·python·macos
JaydenAI20 小时前
[拆解LangChain执行引擎]三种持久化模式的差异
python·langchain
溪水西流20 小时前
NodifyEditor Zoom 机制分析
开发语言·c#·avalonia
老赵全栈实战20 小时前
《从零搭建RAG系统第4天:问题向量化+Milvus检索匹配+结果优化》
python·ai编程
xyq202420 小时前
Go 语言范围(Range)
开发语言