python – 以数字形式布局图像

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

《python – 以数字形式布局图像》

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

谁能指出我正确的方向?

最佳答案
jsheperd shows如何将文本转换为ASCII艺术.您可以稍微修改该代码以获得字形掩码 – 1表示字体为黑色,0表示有背景.然后,我们可以使用PIL随机旋转并粘贴面具为1的面部.

下面我使用matplotlib来获取(Ada Lovelace)的图像,我们假设你已经安装了matplotlib.您可以删除matplotlib依赖项,只需将面重新定义为一系列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 – 以数字形式布局图像》

min_sep是人脸图像之间的最小平方距离.如果增加min_sep参数,则面将间隔得更远.如果减少min_sep,则面可能会更密集地重叠.

点赞