大家好,我是小小明,
使用微信也有那么多年了,你有想過要給你的微信好友的頭像生成圖片墻嗎?
例如:


注意:從效果看有不少重復頭像,這只是因為我本地并沒有那么多微信頭像,只能重復選取,對于微信好友多的朋友,只需要把文章中
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")
path
'C:\\Users\\ASUS/Documents/WeChat Files/你的微信號/FileStorage/General/HDHeadImage'
wechat_id是你的微信號,
~/Documents取決于你沒有修改微信檔案默認保存位置,如果已經修改的情況下需要改成你修改過的檔案夾,
然后就可以通過該檔案夾看到你在電腦上點開過頭像的高清快取:

讀取高清大圖影像快取,就可以再微信電腦版的這個位置讀取到,
但如果我們想獲取所有微信頭像的小圖快取呢?這個時候無法通過微信電腦版直接獲取需要的資料,但我們可以借助有root權限的手機拿到小圖快取(幾乎能包含所有的小圖快取),
我使用了夜神模擬器,通過夜神模擬器登錄個人微信后,多游覽一段時間后,本地就會產生頭像快取,
然后進入/data/data/com.tencent.mm/MicroMsg檔案夾:

再進入最近產生修改而且名稱比較長的檔案夾,其中的avatar檔案夾就存放了所有的頭像快取:

此時將其復制到夜神模擬器的安卓共享路徑,就可以在PC端上讀取到這些圖片檔案了:

不過圖片檔案都在一個個的子檔案夾中,這里我使用everything搜索目標檔案夾,然后將里面的圖片一次性全部剪切出來:

提取出來后就是這樣的效果:

準備好了頭像路徑之后,咱們開始繪制文字:
📣繪制文字圖案?
為了制作文字照片墻,需要在繪制出文字后,分析像素點決定哪些位置擺放照片,
這里依然是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("好友頭像"))
分別用華文琥珀和默認的微軟雅黑粗體測驗一下:

??繪制文字照片墻🔚
獲取到文字圖案的灰度影像物件,就可以很輕松的繪制文字照片墻了,
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))
new_img
生成結果:

可以看到我們已經順利的給圖片串列生成了照片墻,以后的中秋節,國慶節,情人節,都可以直接用,我們不僅僅可能使用文字生成照片墻,也可能根據特殊的形狀圖片,為了方便以后使用,將上述邏輯封裝一下:
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
呼叫示例:
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))

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))

??Python繪制愛心圖案💖
想畫出愛心圖案照片墻,首先得使用PIL畫出愛心圖案,繪制愛心的函式有很多種,下面我分別演示一下,并先用matplotlib實作愛心影像的繪制,
最流行的引數方程是:
x ( t ) = 16 sin ? t 3 x(t)=16 {\sin t}^3 x(t)=16sint3
y ( t ) = 13 cos ? t ? 5 cos ? 2 t ? 2 cos ? 3 t ? cos ? 4 t y(t)=13\cos t- 5\cos 2t - 2\cos 3t -\cos4t y(t)=13cost?5cos2t?2cos3t?cos4t
這個引數方程用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");

對x軸和y軸均加個偏移即使使其落在大于0的區間內,
繪制一個實心愛心:
plt.fill(x+15, y+15, color="r");

不過這種引數方程的形式只是得到邊界的點坐標,要轉換到繪制到PIL影像中還比較困難,下面我使用另一個不流行的心形函式方程進行繪制,函式方程分別由上下兩個方程組成,
上半部分方程為: f ( x ) = 2 ? x 2 ? x 2 f(x)=\sqrt{2 \cdot \sqrt{x^{2}}-x^{2}} f(x)=2?x2 ??x2 ?
下半部分方程為: g ( x ) = ? 2.14 ? 2 ? ∣ x ∣ g(x)=-2.14 \cdot \sqrt{\sqrt{2}-\sqrt{|x|}} g(x)=?2.14?2 ??∣x∣ ? ?
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();

如何將其偏移到正數范圍呢?我采用下面的方式:
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();

同時有上下兩個函式方程時,畫實心愛心也很簡單:
plt.fill_between(x, gx, fx, color="r");

接下來我們去掉軸,并保存圖片,就可以直接用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")
im

現在需要去除多余的空白,對于這種黑白影像,我直接使用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))

💕繪制愛心照片墻💘
有了上的愛心蒙版就可以很簡單的繪制出照片墻了,
為了減少最后的渲染量,將愛心圖片縮放一下:
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))

當然一些系統相關的快取也被加入到了圖片串列,可以再人工洗掉這些系統圖示后再進行生成,
🚩繪制任意圖形照片墻🚀
其實我并不是一定要自己畫一個愛心圖形之后,才能畫愛心照片墻,只要我們事先準備好圖形的蒙版圖片,用PIL讀取后轉換一下即可馬上畫成相應的照片墻,
這里有個微詞云的網站:https://www.weiciyun.com/edit
可以下載各種各樣的蒙版形狀:

我們以大拇指為例進行演示,首先下載目標圖片:
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))

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

將以上代碼封裝一下:
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")

💎看完本文,相信你已經任何形式的照片墻都會畫了吧???
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/295228.html
標籤:其他
