我有一个包含小图片(Facebook 个人资料图片)的文件夹。我想制作一个新的类似马赛克的图片,其中所有的小图片都以数字的形式排列,就像这个例子( source )。

python - 以数字形式排列图像-LMLPHP

是否有可以执行此操作的软件程序(并且在 Windows 7 上运行)?
否则,我也愿意编写一个小脚本来做同样的事情。
我知道如何使用 PIL/Pillow 为图像添加白色边框,但我对如何布局图像的搜索无果而终。

任何人都可以指出我正确的方向吗?

最佳答案

jsheperd shows 如何将文本转换为 ASCII 艺术。您可以稍微修改该代码以获得字形掩码——字体为黑色时为 1,背景为 0 时。然后我们可以使用 PIL 在蒙版为 1 的地方随机旋转和粘贴一张脸。
下面我使用 matplotlib 只是为了获取(Ada Lovelace 的)图像,假设您安装了 matplotlib,我们都会拥有该图像。您可以删除 matplotlib 依赖项,只需将 faces 重新定义为 PIL 图像序列。

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import itertools as IT
import numpy as np
import matplotlib.cbook as cbook

def text_to_pixels(text, path='arialbd.ttf', fontsize=14):
    """
    https://stackoverflow.com/a/27753869/190597 (jsheperd)
    https://stackoverflow.com/a/36386628/190597 (unutbu)
    """
    font = ImageFont.truetype(path, fontsize)
    w, h = font.getsize(text)
    h *= 2
    image = Image.new('L', (w, h), 1)
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), text, font=font)
    arr = np.asarray(image)
    arr = np.where(arr, 0, 1)
    arr = arr[(arr != 0).any(axis=1)]
    return arr

def get_image():
    fn = cbook.get_sample_data("ada.png")
    face_img = Image.open(fn).convert('RGBA')
    face_img = face_img.resize((30, 40), Image.ANTIALIAS)
    # give image a white background
    img = Image.new('RGBA', size=(36, 46), color=(255, 255, 255))
    img.paste(face_img, (3, 3))
    return img

def sqdist(a, b):
    return ((a -b)**2).sum()

def pics_in_text(text, faces, img_width=600, img_height=250, path='arialbd.ttf',
                 fontsize=20, minsep=1000):
    arr = text_to_pixels(text, path=path, fontsize=fontsize)
    yx = np.column_stack(np.where(arr)).astype(float)
    yx /= arr.shape
    yx *= (0.75, 0.90)
    yx += 0.05
    yx *= (img_height, img_width)
    yx = yx.astype('int')
    np.random.shuffle(yx)
    keep = []
    for coord in yx:
        if all(sqdist(item, coord) > minsep for item in keep):
            keep.append(coord)
    yx = IT.cycle(keep)

    img = Image.new('RGBA', size=(img_width, img_height), color=(255, 255, 255, 255))
    seen = list()
    for face, coord in zip(faces, yx):
        deg = np.random.uniform(-45, 45)
        face = face.rotate(deg, resample=Image.BICUBIC, expand=False)
        img.paste(face, tuple(coord[::-1]), mask=face)
    return img

def get_image():
    import matplotlib.cbook as cbook
    fn = cbook.get_sample_data("ada.png")
    face_img = Image.open(fn).convert('RGBA')
    face_img = face_img.resize((30, 40), Image.ANTIALIAS)
    # give image a white background
    img = Image.new('RGBA', size=(36, 46), color=(255, 255, 255))
    img.paste(face_img, (3, 3))
    return img

num_faces = 650
faces = IT.islice(IT.cycle([get_image()]), num_faces)
img = pics_in_text('800', faces, img_width=1200, img_height=500,
             path='/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf',
             fontsize=40, minsep=375)
img.save('/tmp/out.png', 'PNG')
python - 以数字形式排列图像-LMLPHPmin_sep 是人脸图像之间的最小平方距离。如果增加 min_sep 参数,则面将间隔得更远。如果减少 min_sep,则面可能会更密集地重叠。

关于python - 以数字形式排列图像,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36479510/

10-11 23:19
查看更多