有趣的Python圖片製作,用QQ好友頭像拼接出里昂

在本篇博客中,我們將實現兩個功能:

  • 將所有頭像合併為大圖
  • 將所有頭像以某個模板合成大圖

同樣,先給上所有運行效果圖:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂


代碼實現

1、代碼所需庫

import requests,codecs,re,urllib,os,random,math

from PIL import Image

import numpy as np

import cv2 as cv

2、代碼講解

本篇博客就不再講解如何獲取好友頭像了,需要的可以參考這篇博文:

python爬蟲-從QQ郵箱獲取好友信息並爬取頭像

現在,我們已經有了所有的好友頭像,接下來我們先實現對所有頭像的集合咯

有趣的Python圖片製作,用QQ好友頭像拼接出里昂

2.1、將小頭像合併為大圖

對於這個,就是直接將每個小頭像貼在大圖上就行了,這個利用Image的paste函數就可以解決。對於貼的順序就可以直接按照下面圖示一個個貼:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂

所以,直接給出代碼:

def simple_split(filepackage,size,littlesize): #簡單拼接,參數為圖片文件名,每行每列的size,小頭像圖片的大小

row = size[0]

col = size[1]

bigimg = Image.new('RGBA',(littlesize*row,littlesize*col)) #結果圖

number = 0

for i in range(row): #行

for j in range(col): #列

randpic = random.randint(1,friends_count)

img = Image.open(filepackage+str(randpic)+'.png').convert('RGBA')

img = img.resize((littlesize,littlesize))

loc = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize)

print(loc,number)

number+=1

bigimg.paste(img,loc)

bigimg.save(resultSavePath)

由於好友不多,所以我們每次就隨機選擇一個好友頭像貼上去,所以如果你的密度大的話最後出現的頭像有很多重複的頭像。

給大家展示下最後我的圖片吧:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂


2.2、以某個圖片為模板拼接圖片

由於不清楚有沒有能夠直接做出來的第三方庫,所有我就自己造了個小輪子。

思路:

將模板分為A x B的小圖,就將它的位置形容為 pic[i][j] 吧,然後獲取每個小圖的平均RGB值,將 pic[i][j] 的平均RGB值和好友頭像的RGB值做對比,找出最接近的頭像,然後將該頭像插入在圖像的 pic[i][j] 處。

思路還是比較簡單吧

接下來就是實現了:

代碼很多地方都給出了註釋,我就不多講了,直接給出代碼:

import requests,codecs,re,urllib,os,random,math

from PIL import Image

import numpy as np

import cv2 as cv

txtpath = 'C:/Users/11037/Desktop/test/qqfriends.txt' #你從QQ郵箱中粘貼的文件

savepath = 'C:/Users/11037/Desktop/touxiang/' #頭像存儲位置

resultSavePath = 'C:/Users/11037/Desktop/result2.png' #結果存儲位置

modePath = 'C:/Users/11037/Desktop/leno.jpg' #模板存儲位置

friends_count = 0 #好友數量

all_mean_rgbs = [] #存儲計算出的所有平均rgb值

def meanrbg(img): #計算圖片平均rgb

rgb = np.array(img)

r = int(round(np.mean(rgb[:, :, 0])))

g = int(round(np.mean(rgb[:, :, 1])))

b = int(round(np.mean(rgb[:, :, 2])))

return (r,g,b)

def gettouxiang(txtpath):#輸入你的txt文件存儲位置

file = codecs.open(txtpath,'rb','utf-8')

s = file.read()

pattern = re.compile(r'\[email protected]')

all_mail = pattern.findall(s) #正則表達式匹配所有的qq號

all_link = [] #用於存儲需要訪問的鏈接

url = 'http://qlogo.store.qq.com/qzone/'

for mail in all_mail:

qq = mail.replace('@qq.com','')

l = url + qq +'/'+qq+'/100'

all_link.append(l)

i = 1

for link in all_link: #遍歷鏈接,下載頭像

saveurl = savepath+str(i)+'.png'

savaImg(link,saveurl)

i +=1

print('已下載',i)

friends_count = len(all_link) #獲取朋友頭像數量

return True

def savaImg(picurl,saveurl): #存儲圖片函數,picurl是圖片的URL,saveurl是本地存儲位置

try:

bytes = urllib.request.urlopen(picurl)

file = open(saveurl,'wb')

file.write(bytes.read())

file.flush()

file.close()

return True

except:

print('worry')

savaImg(picurl,saveurl)

def simple_split(filepackage,size,littlesize): #簡單拼接,參數為圖片文件名,每行每列的size,小頭像圖片的大小

row = size[0]

col = size[1]

bigimg = Image.new('RGBA',(littlesize*row,littlesize*col))

number = 0

for i in range(row):

for j in range(col):

randpic = random.randint(1,friends_count)

img = Image.open(filepackage+str(randpic)+'.png').convert('RGBA')

img = img.resize((littlesize,littlesize))

loc = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize)

print(loc,number)

number+=1

bigimg.paste(img,loc)

bigimg.save(resultSavePath)

def mode_split(filepackage,modepath,bigsize,littlesize): #以模板存儲頭像

row = bigsize[0] #大圖每行多少個小頭像

col = bigsize[1] #每列

suitSize = (littlesize*row,littlesize*col) #大圖最終的像素size

bigImg = Image.open(modepath)

bigImg = bigImg.resize(suitSize)

resultImg = Image.new('RGBA',suitSize)

for i in range(row):

for j in range(col):

cutbox = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize) #模板剪切用於對比的某個區域

cutImg = bigImg.crop(cutbox) #複製到cutImg中

tmprgb = meanrbg(cutImg)

suitOne = mostSuitImg(tmprgb) + 1 #對比出最合適的頭像

img = Image.open(filepackage + str(suitOne) + '.png').convert('RGBA')

img = img.resize((littlesize,littlesize))

resultImg.paste(img,cutbox)

print('已粘貼',cutbox)

resultImg.save(resultSavePath) #存儲

def mostSuitImg(tmprgb): #進行對比,找出最合適的頭像

global all_mean_rgbs

minRange = 200000

id = 0

for rgb in all_mean_rgbs:

tmp = (rgb[1][0]-tmprgb[2])**2+(rgb[1][1]-tmprgb[1])**2+(rgb[1][2]-tmprgb[1])**2

if tmp

minRange = tmp

id = rgb[0]

return id

if __name__ == '__main__':

# gettouxiang(txtpath) #獲取頭像,如果已經獲取就可以給註釋掉了

# simple_split(savepath,(20,20),30) #簡單拼接

#模板拼接

for i in range(1,friends_count+1):

img = cv.imread(savepath+str(i)+'.png')

rgb = meanrbg(img)

all_mean_rgbs.append(rgb)

all_mean_rgbs = list(enumerate(all_mean_rgbs)) #給列表增加一個索引

mode_split(savepath,modePath,(50,80),20) #模板拼接

給大家看看最終的效果:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂


這樣一看還是都不錯是吧。哈哈。

再給出里昂的模板和最終成果:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂


有趣的Python圖片製作,用QQ好友頭像拼接出里昂


添加【修改後的Leon】:

有趣的Python圖片製作,用QQ好友頭像拼接出里昂


我默認將每個頭像以數字命名,可以便於後續的操作。

同時,以上代碼都進行了封裝,很多函數都可以獨立使用,用於滿足不同的功能。可以自己讀完代碼進行改寫實現自己需要的功能,比如說以上我默認頭像圖片都是正方形,你如果圖片有長方形的改變下代碼也可以滿足。

理論上來說,你的好友頭像越多,製作出來的圖片與模板的差異也就越小。以mode_split這個函數為例,你設置的bigsize越大,你的圖片也就越清晰。

以上代碼有不足的地方還請大家多多包涵。水平有限,我們,都在努力奔跑~

有趣的Python圖片製作,用QQ好友頭像拼接出里昂



分享到:


相關文章: