以数字形式布置图像
Layout images in form of a number
我有一个包含小图片(Facebook 个人资料图片)的文件夹。我想制作一个新的类似马赛克的图片,其中所有的小图片都以数字的形式排列,就像这个例子 (source).
是否有可以执行此操作的软件程序(并且在 Windows 7 上运行)?
否则我也愿意编写一个小脚本来做同样的事情。
我知道如何使用 PIL/Pillow 为图像添加白色边框,但我搜索如何布置图像却毫无结果。
谁能指出我正确的方向?
jsheperd shows 如何将文本转换为 ASCII 艺术。您可以稍微修改该代码以获得字形掩码——字体为黑色的 1 和有背景的 0。然后我们可以使用 PIL 在掩码为 1 的任何地方随机旋转并粘贴一张脸。
下面我使用 matplotlib
只是为了获取我们都假设您已安装 matplotlib
的图像(Ada Lovelace)。您可以删除 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):
"""
(jsheperd)
(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')
min_sep
是人脸图像之间的最小平方距离。如果增加 min_sep
参数,面的间距会更大。如果减少 min_sep
,则面可能会更密集地重叠。
我有一个包含小图片(Facebook 个人资料图片)的文件夹。我想制作一个新的类似马赛克的图片,其中所有的小图片都以数字的形式排列,就像这个例子 (source).
是否有可以执行此操作的软件程序(并且在 Windows 7 上运行)? 否则我也愿意编写一个小脚本来做同样的事情。 我知道如何使用 PIL/Pillow 为图像添加白色边框,但我搜索如何布置图像却毫无结果。
谁能指出我正确的方向?
jsheperd shows 如何将文本转换为 ASCII 艺术。您可以稍微修改该代码以获得字形掩码——字体为黑色的 1 和有背景的 0。然后我们可以使用 PIL 在掩码为 1 的任何地方随机旋转并粘贴一张脸。
下面我使用 matplotlib
只是为了获取我们都假设您已安装 matplotlib
的图像(Ada Lovelace)。您可以删除 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):
"""
(jsheperd)
(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')
min_sep
是人脸图像之间的最小平方距离。如果增加 min_sep
参数,面的间距会更大。如果减少 min_sep
,则面可能会更密集地重叠。