如何破解《楚门的世界》马赛克海报?附完整教程!

0616cf22e95bba81a6f3b0485189cc7b.png

点击上方“蓝字”关注我们

看了电影《楚门的世界》的海报,是不是觉得特别炫酷?将各个图片拼在一起,最后呈现为主角,在那个年代,这种海报制作堪称一绝!

别羡慕,你也可以完成!

82d61ad823c20f3ca3731534363fe4e2.png

在开始之前,你有没有想过上面的图片是怎么实现的?难道这是用 ps 一张张拼起来的?光靠人工把近千张图片按照色域一一排列,这个可能性几乎为0

所以,马赛克图片生成器就产生了。那么今天,我们就用 Python 做一个马赛克图片生成器。只需要 200 行 Python 代码,就可以将任意图片转换成马赛克效果。既可以用来记录校园生活、游戏生涯,又可以用作礼物。

2aa1e6609d8b5505861a2e2d03d8a98e.png

01

项目思路

项目大概分为 3 个步骤:

  1. 计算素材库中每张图片的平均色

  2. 把目标图片切分成平均的色块,与素材库图片进行替换

  3. 全部替换完成后,再与原始图像进行融合

9d6b191ae17259ee4383f78ccc40294f.png

02

计算图像平均值

一张图像,是通过许多的像素组成的。为了生成马赛克图片,我们的想法是,将原有图像的每一个小部分,使用颜色与这一小部分相似的图像进行替换,从而生成马赛克风格的图像。

如何计算图片的颜色相似度?这里要引用 RGB 和 HSV 的概念。

RGB 色彩空间是,由三个通道表示一幅图像。三个通道分别为红色 (R),绿色 (G) 和蓝色(B),通过这三种颜色的不同组合,可以形成几乎所有的其他颜色。

outside_default.png

但是,在自然环境下,图像容易受自然光照、遮挡等情况的影响,也就是人眼观察图片会对图片的亮度比较敏感。而 RGB 色彩空间的三个分量都与亮度密切相关,只要亮度改变,RGB 颜色的三个分量都会改变。

同时,由于人眼对于这 RGB 这三种颜色的敏感程度是不一样的。在单色中,人眼对红色最不敏感,蓝色最敏感,所以 RGB 色彩空间是一种均匀性较差的色彩空间。

由于 RGB 色彩空间不能方便的比较颜色之间的相似度,于是我们要使用 HSV 色彩空间。HSV 色彩空间也是由三个分量组成的,分别是:

  • Hue(色调)

  • Saturation (饱和度)

  • Value (明度)

我们会常用下图的圆柱体来表示 HSV 色彩空间,其中:

  • H 用极坐标的极角表示;

  • S 用极坐标的轴的长度表示;

  • V 用圆柱的高度表示。

0b5de3c654ce7079f67e7437d1ac7949.png

计算图片 HSV 值的代码如下:

class mosaic(object):
    """定义计算图片的平均hsv值
    """
    def __init__(self, IN_DIR: str, OUT_DIR: str, SLICE_SIZE: int, REPATE: int,
                 OUT_SIZE: int) -> None:
        self.IN_DIR = IN_DIR  # 原始的图像素材所在文件夹
        self.OUT_DIR = OUT_DIR  # 输出素材的文件夹, 这些都是计算过hsv和经过resize之后的图像
        self.SLICE_SIZE = SLICE_SIZE  # 图像放缩后的大小
        self.REPATE = REPATE  # 同一张图片可以重复使用的次数
        self.OUT_SIZE = OUT_SIZE  # 最终图片输出的大小

    def resize_pic(self, in_name: str, size: int) -> Image:
        """转换图像大小
        """
        img = Image.open(in_name)
        img = ImageOps.fit(img, (size, size), Image.ANTIALIAS)
        return img

    def get_avg_color(self, img: Image) -> Tuple[float, float, float]:
        """计算图像的平均hsv
        """
        width, height = img.size
        pixels = img.load()
        if type(pixels) is not int:
            data = []  # 存储图像像素的值
            for x in range(width):
                for y in range(height):
                    cpixel = pixels[x, y]  # 获得每一个像素的值
                    data.append(cpixel)
            h = 0
            s = 0
            v = 0
            count = 0
            for x in range(len(data)):
                r = data[x][0]
                g = data[x][1]
                b = data[x][2]  # 得到一个点的GRB三色
                count += 1
                hsv = rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)
                h += hsv[0]
                s += hsv[1]
                v += hsv[2]

            hAvg = round(h / count, 3)
            sAvg = round(s / count, 3)
            vAvg = round(v / count, 3)

            if count > 0:  # 像素点的个数大于0
                return (hAvg, sAvg, vAvg)
            else:
                raise IOError("读取图片数据失败")
        else:
            raise IOError("PIL 读取图片数据失败")

以上内容出自蓝桥云课免费课程—— Python 制作马赛克拼合图像,但由于篇幅有限,无法一一呈现。如果你有任何代码问题,欢迎大家随时通过文末方式和我交流。

80032d59f0ae2b9e73882236acda5a43.png

44a4e73242e756905daf1d7f7f7fc100.gif

戳戳“阅读原文”直达课程页面!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值