0
点赞
收藏
分享

微信扫一扫

❤️为你的微信制作好友头像照片墙吧⁉️


​​

大家好,我是小小明。

使用微信也有那么多年了,你有想过要给你的微信好友的头像生成图片墙吗?

例如:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_02

注意:从效果看有不少重复头像,这只是因为我本地并没有那么多微信头像,只能重复选取。对于微信好友多的朋友,只需要把文章中​​np.random.choice(imgs, size=data.sum())​​​这行代码加个参数​​replace=False​​就能实现非重复选取。

如果有跟我一样想法的朋友,咱们Let’s go⏩👊。

文章目录

  • ​​🌀获取微信头像的缓存列表🌀​​
  • ​​📣绘制文字图案⏩​​
  • ​​⭐️绘制文字照片墙🔚​​
  • ​​❤️Python绘制爱心图案💖​​
  • ​​💕绘制爱心照片墙💘​​
  • ​​🚩绘制任意图形照片墙🚀​​


首先我们需要先获取微信头像的缓存列表:

🌀获取微信头像的缓存列表🌀

在我们自己点开过目标的头像查看大图时,微信电脑版会将其保存到​​HDHeadImage​​(高清大图)目录中。

这个目标可以直接通过python读取到:

wechat_id = "你的微信号"
path = os.path.expanduser(f"~/Documents/WeChat Files/{wechat_id}/FileStorage/General/HDHeadImage")

'C:\\Users\\ASUS/Documents/WeChat Files/你的微信号/FileStorage/General/HDHeadImage'

​wechat_id​​是你的微信号。

​~/Documents​​取决于你没有修改微信文件默认保存位置。如果已经修改的情况下需要改成你修改过的文件夹。

然后就可以通过该文件夹看到你在电脑上点开过头像的高清缓存:

❤️为你的微信制作好友头像照片墙吧⁉️_照片墙_03

读取高清大图图像缓存,就可以再微信电脑版的这个位置读取到。

但如果我们想获取所有微信头像的小图缓存呢?这个时候无法通过微信电脑版直接获取需要的数据,但我们可以借助有root权限的手机拿到小图缓存(几乎能包含所有的小图缓存)。

我使用了夜神模拟器,通过夜神模拟器登录个人微信后,多游览一段时间后,本地就会产生头像缓存。

然后进入​​/data/data/com.tencent.mm/MicroMsg​​文件夹:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_04

再进入最近产生修改而且名称比较长的文件夹,其中的​​avatar​​文件夹就存放了所有的头像缓存:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_05

此时将其复制到夜神模拟器的安卓共享路径,就可以在PC端上读取到这些图片文件了:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_06

不过图片文件都在一个个的子文件夹中,这里我使用​​everything​​搜索目标文件夹,然后将里面的图片一次性全部剪切出来:

❤️为你的微信制作好友头像照片墙吧⁉️_微信_07

提取出来后就是这样的效果:

❤️为你的微信制作好友头像照片墙吧⁉️_微信_08

准备好了头像路径之后,咱们开始绘制文字:

📣绘制文字图案⏩

为了制作文字照片墙,需要在绘制出文字后,分析像素点决定哪些位置摆放照片。

这里依然是PIL库进行文字绘制,经过多次调试,设计出如下绘制方法:

from PIL import Image, ImageFont, ImageDraw, ImageChops


def create_text_img(text, size=30, fontname="msyhbd.ttc"):
"作者:小小明"
# 获取字体对象
font = ImageFont.truetype(fontname, size)
width = len(text) * size

# 左上角对齐绘制文字
im = Image.new(mode='RGBA', size=(width, size))
draw = ImageDraw.Draw(im=im)
w, h = draw.textsize(text, font)
o1, o2 = font.getoffset(text)
draw.text(xy=(-o1, -o2), text=text,
fill="black", font=font)

# 裁切文字多余空白
bg = Image.new(mode='RGBA', size=im.size)
bbox = ImageChops.difference(im, bg).getbbox()
im = im.crop(bbox)
text_img = Image.new(mode='L', size=im.size, color=255)
text_img.paste(im, mask=im)
return text_img


display(create_text_img("好友头像", fontname="STHUPO.TTF"))
display(create_text_img("好友头像"))

分别用华文琥珀和默认的微软雅黑粗体测试一下:

❤️为你的微信制作好友头像照片墙吧⁉️_微信_09

⭐️绘制文字照片墙🔚

获取到文字图案的灰度图像对象,就可以很轻松的绘制文字照片墙了。

import numpy as np

im = create_text_img("照片墙", fontname="msyh.ttc")
data = np.array(im) != 255
h, w = data.shape
print(f"共需{data.sum()}张图片,宽{w}张,高{h}张")

共需1115张图片,宽90张,高29张

我使用了​​照片墙​​作为文字图片,显示共需1890张头像图片,但是我的缓存文件夹并没有这么多图片,只能允许头像能够被重复选取。

获取随机头像列表:

import os

img_path = r"C:\Users\ASUS\Nox_share\ImageShare\avatar"
imgs = os.listdir(img_path)
img_lists = np.random.choice(imgs, size=data.sum())

然后就可以生成头像照片墙了:

# 设置每个头像的大小
size = 50
new_img = Image.new('RGB', (size * w, size * h), "white")
random_imgs = iter(img_lists)

for y, x in zip(*np.where(data)):
img_name = next(random_imgs)
src_img = Image.open(f'{img_path}/{img_name}')
src_img = src_img.resize((size, size), Image.ANTIALIAS)
# 将图片复制到 new_image
new_img.paste(src_img, (x * size, y * size))

生成结果:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存

可以看到我们已经顺利的给图片列表生成了照片墙,以后的中秋节,国庆节,情人节,都可以直接用。我们不仅仅可能使用文字生成照片墙,也可能根据特殊的形状图片,为了方便以后使用,将上述逻辑封装一下:

def create_picture_wall(data, imgs, size=50):
h, w = data.shape
random_imgs = iter(np.random.choice(imgs, size=data.sum()))

new_img = Image.new('RGB', (size * w, size * h), "white")
for y, x in zip(*np.where(data)):
img_name = next(random_imgs)
src_img = Image.open(f'{img_path}/{img_name}')
src_img = src_img.resize((size, size), Image.ANTIALIAS)
# 将图片复制到 new_image
new_img.paste(src_img, (x * size, y * size))
return

调用示例:

im = create_text_img("小小明")
img_path = r"C:\Users\ASUS\Nox_share\ImageShare\avatar"
create_picture_wall(np.array(im) != 255, os.listdir(img_path))

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_11

im = create_text_img("小小明", fontname="msyh.ttc")
img_path = r"C:\Users\ASUS\Nox_share\ImageShare\avatar"
create_picture_wall(np.array(im) != 255, os.listdir(img_path))

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_12

❤️Python绘制爱心图案💖

想画出爱心图案照片墙,首先得使用PIL画出爱心图案。绘制爱心的函数有很多种,下面我分别演示一下,并先用matplotlib实现爱心图像的绘制。

最流行的参数方程是:

这个参数方程用python表达就是:

import math
import numpy as np

t = np.arange(0, 2*math.pi, 0.1)
x = 16*np.sin(t)**3
y = 13*np.cos(t)-5*np.cos(2*t)-2*np.cos(3*t)-np.cos(4*t)

用matplotlib可以直接绘制:

from matplotlib import pyplot as plt

plt.plot(x, y, color="r");

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_15

对x轴和y轴均加个偏移即使使其落在大于0的区间内。

绘制一个实心爱心:

plt.fill(x+15, y+15, color="r");

❤️为你的微信制作好友头像照片墙吧⁉️_微信_16

不过这种参数方程的形式只是得到边界的点坐标,要转换到绘制到PIL图像中还比较困难。下面我使用另一个不流行的心形函数方程进行绘制,函数方程分别由上下两个方程组成。

上半部分方程为:

下半部分方程为:

import math
from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(-2, 2, 1000)
fx = np.sqrt(2*np.abs(x)-x**2)
gx = -2.14*np.sqrt(np.sqrt(2)-np.sqrt(np.abs(x)))

plt.plot(x, fx, color="r", label="upper")
plt.plot(x, gx, color="b", label="down")
plt.legend();

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_19

如何将其偏移到正数范围呢❓我采用下面的方式:

import math
from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(-2, 2, 2000)
fx = np.sqrt(2*np.abs(x)-x**2)
gx = -2.14*np.sqrt(np.sqrt(2)-np.sqrt(np.abs(x)))

x = (x+2)*7.5
fx = (fx+2.5)*7.5
gx = (gx+2.5)*7.5
plt.plot(x, fx, color="r", label="upper")
plt.plot(x, gx, color="b", label="down")
plt.legend();

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_20

同时有上下两个函数方程时,画实心爱心也很简单:

plt.fill_between(x, gx, fx, color="r");

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_21

接下来我们去掉轴,并保存图片,就可以直接用PIL读取了。

产生爱心图像并保存到文件中:

import math
from PIL import Image
from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(-2, 2, 100)
fx = np.sqrt(2*np.abs(x)-x**2)
gx = -2.14*np.sqrt(np.sqrt(2)-np.sqrt(np.abs(x)))

fx = (fx+2.5)*7
gx = (gx+2.5)*7
fig = plt.figure()
plt.axis("off")
plt.fill_between(x, gx, fx, color="black")
fig.savefig("t.jpg");

读取图片并转换为黑白图像:

im = Image.open("t.jpg").convert("1")

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_22

现在需要去除多余的空白,对于这种黑白图像,我直接使用numpy去除边界上的空白。

首先转换为numpy数组:

data = ~np.array(im)
print("去除前:")
display(Image.fromarray(data))
ys, xs = np.where(data)
data = data[min(ys):max(ys)+1, min(xs):max(xs)+1]
print("去除后:")
display(Image.fromarray(data))

❤️为你的微信制作好友头像照片墙吧⁉️_微信_23

💕绘制爱心照片墙💘

有了上的爱心蒙版就可以很简单的绘制出照片墙了。

为了减少最后的渲染量,将爱心图片缩放一下:

im = Image.fromarray(data).resize((60, 40), Image.ANTIALIAS)
data = np.array(im)
h, w = data.shape
print(f"共需{data.sum()}张图片,宽{w}张,高{h}张")

共需1504张图片,宽60张,高40张

然后开始绘制:

import os

def create_picture_wall(data, imgs, size=50):
h, w = data.shape
random_imgs = iter(np.random.choice(imgs, size=data.sum()))

new_img = Image.new('RGB', (size * w, size * h), "white")
for y, x in zip(*np.where(data)):
img_name = next(random_imgs)
src_img = Image.open(f'{img_path}/{img_name}')
src_img = src_img.resize((size, size), Image.ANTIALIAS)
# 将图片复制到 new_image
new_img.paste(src_img, (x * size, y * size))
return new_img


img_path = r"C:\Users\ASUS\Nox_share\ImageShare\avatar"
create_picture_wall(data, os.listdir(img_path))

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_02

当然一些系统相关的缓存也被加入到了图片列表,可以再人工删除这些系统图标后再进行生成。

🚩绘制任意图形照片墙🚀

其实我并不是一定要自己画一个爱心图形之后,才能画爱心照片墙。只要我们事先准备好图形的蒙版图片,用PIL读取后转换一下即可马上画成相应的照片墙。


可以下载各种各样的蒙版形状:

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_25

我们以大拇指为例进行演示,首先下载目标图片:

import requests
from io import BytesIO

url = "https://staticc.ywordle.com/static/2020-11-01/6d2e4f9d31d1b7201e23198869de2f9a_preview.png"
r = requests.get(url)
im = Image.open(BytesIO(r.content))
im.size

(190, 200)

图片过大,转换为bool数组,并缩放一下:

data = np.array(im) > 0
data = np.array(Image.fromarray(data).resize((48, 50), Image.ANTIALIAS))
display(Image.fromarray(data))

❤️为你的微信制作好友头像照片墙吧⁉️_缓存_26

然后就可以生成大拇指的照片墙了:

❤️为你的微信制作好友头像照片墙吧⁉️_照片墙_27

将以上代码封装一下:

from PIL import Image
import requests
from io import BytesIO
import os


def get_mask_data(im, size=50):
width, height = im.size
if width > height:
height = height*size//width
width = size
else:
width = width*size//height
height = size
im = im.resize((width, height), Image.ANTIALIAS)
return np.array(im) > 0


def create_picture_wall(data, img_path, size=50):
h, w = data.shape
imgs = os.listdir(img_path)
random_imgs = iter(np.random.choice(imgs, size=data.sum()))
new_img = Image.new('RGB', (size * w, size * h), "white")
for y, x in zip(*np.where(data)):
img_name = next(random_imgs)
src_img = Image.open(f'{img_path}/{img_name}')
src_img = src_img.resize((size, size), Image.ANTIALIAS)
new_img.paste(src_img, (x * size, y * size))
return new_img


def download_img(url):
r = requests.get(url)
return Image.open(BytesIO(r.content))

测试一下:

url = "https://staticc.ywordle.com/static/2020-11-03/f18f814d52768eb29111c0be52b14ca2_preview.png"
im = download_img(url)
data = get_mask_data(im)
create_picture_wall(data, r"C:\Users\ASUS\Nox_share\ImageShare\avatar")

❤️为你的微信制作好友头像照片墙吧⁉️_微信_28

💎看完本文,相信你已经任何形式的照片墙都会画了吧?☀️


举报

相关推荐

0 条评论