有趣的Python图片制作之如何用QQ好友头像拼接出里昂


Posted in Python onApril 22, 2020

在本篇博客中,我们将实现两个功能:

  • 将所有头像合并为大图
  • 将所有头像以某个模板合成大图

同样,先给上所有运行效果图:

有趣的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'\d+@qq.com')
	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:
			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好友头像拼接出里昂的文章就介绍到这了,更多相关python 好友头像拼接内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
Jul 18 Python
提升Python程序运行效率的6个方法
Mar 31 Python
Ruby使用eventmachine为HTTP服务器添加文件下载功能
Apr 20 Python
一些常用的Python爬虫技巧汇总
Sep 28 Python
django2 快速安装指南分享
Jan 05 Python
Python利用lxml模块爬取豆瓣读书排行榜的方法与分析
Apr 15 Python
Python内置方法实现字符串的秘钥加解密(推荐)
Dec 09 Python
matlab灰度图像调整及imadjust函数的用法详解
Feb 27 Python
Python设计密码强度校验程序
Jul 30 Python
python中使用.py配置文件的方法详解
Nov 23 Python
python自动化发送邮件实例讲解
Jan 04 Python
numba提升python运行速度的实例方法
Jan 25 Python
python模拟斗地主发牌
Apr 22 #Python
matlab 计算灰度图像的一阶矩,二阶矩,三阶矩实例
Apr 22 #Python
python根据完整路径获得盘名/路径名/文件名/文件扩展名的方法
Apr 22 #Python
matlab中二维插值函数interp2的使用详解
Apr 22 #Python
python 一维二维插值实例
Apr 22 #Python
Numpy一维线性插值函数的用法
Apr 22 #Python
python数据处理——对pandas进行数据变频或插值实例
Apr 22 #Python
You might like
php curl选项列表(超详细)
2013/07/01 PHP
JS模块与命名空间的介绍
2013/03/22 Javascript
asp.net刷新本页面的六种方法总结
2014/01/07 Javascript
js获取当前日期前七天的方法
2015/02/28 Javascript
如何用javascript计算文本框还能输入多少个字符
2015/07/29 Javascript
javascript实现连续赋值
2015/08/10 Javascript
jquery模拟实现鼠标指针停止运动事件
2016/01/12 Javascript
简述Matlab中size()函数的用法
2016/03/20 Javascript
Ext JS动态加载JavaScript创建窗体的方法
2016/06/23 Javascript
简单学习vue指令directive
2016/11/03 Javascript
jQuery html表格排序插件tablesorter使用方法详解
2017/02/10 Javascript
Angular.js自定义指令学习笔记实例
2017/02/24 Javascript
jquery获取链接地址和跳转详解(推荐)
2017/08/15 jQuery
基于Webpack4和React hooks搭建项目的方法
2019/02/05 Javascript
validform表单验证的实现方法
2019/03/08 Javascript
发布订阅模式在vue中的实际运用实例详解
2019/06/09 Javascript
vue下载二进制流图片操作
2020/10/26 Javascript
[39:21]LGD vs OG 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.24
2019/09/10 DOTA
Python 2.7.x 和 3.x 版本的重要区别小结
2014/11/28 Python
tensorflow实现简单的卷积网络
2018/05/24 Python
Python定时任务随机时间执行的实现方法
2019/08/14 Python
对Python获取屏幕截图的4种方法详解
2019/08/27 Python
Python 生成器,迭代,yield关键字,send()传参给yield语句操作示例
2019/10/12 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
2019/11/15 Python
面向对象编程的优势是什么
2015/12/17 面试题
南京迈特望C/C++面试题
2012/07/09 面试题
商场消防演习方案
2014/02/12 职场文书
投资意向书范本
2014/04/01 职场文书
文科毕业生自荐书范文
2014/04/17 职场文书
网络技术专业求职信
2014/07/13 职场文书
小区门卫岗位职责范本
2014/08/24 职场文书
领导干部查摆“四风”问题自我剖析材料思想汇报
2014/10/05 职场文书
工程资料员岗位职责
2015/04/13 职场文书
入学证明
2015/06/23 职场文书
Python使用socket去实现TCP客户端和TCP服务端
2022/04/12 Python
el-form每行显示两列底部按钮居中效果的实现
2022/08/05 HTML / CSS