有趣的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 getopt模块处理命令行选项实例
May 13 Python
进一步了解Python中的XML 工具
Apr 13 Python
Linux RedHat下安装Python2.7开发环境
May 20 Python
利用Anaconda完美解决Python 2与python 3的共存问题
May 25 Python
Python yield与实现方法代码分析
Feb 06 Python
对python 匹配字符串开头和结尾的方法详解
Oct 27 Python
对Python中小整数对象池和大整数对象池的使用详解
Jul 09 Python
使用python代码进行身份证号校验的实现示例
Nov 21 Python
Python reshape的用法及多个二维数组合并为三维数组的实例
Feb 07 Python
Python unittest 自动识别并执行测试用例方式
Mar 09 Python
在服务器上安装python3.8.2环境的教程详解
Apr 26 Python
Python保存并浏览用户的历史记录
Apr 29 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
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
详解Yii2 定制表单输入字段的标签和样式
2017/01/04 PHP
浅谈PHP各环境下的伪静态配置
2019/03/13 PHP
javascript中的float运算精度实例分析
2010/08/21 Javascript
JS操作数据库的实例代码
2013/10/17 Javascript
禁止ajax缓存获取程序最新数据的方法
2013/11/19 Javascript
jquery 获取 outerHtml 包含当前节点本身的代码
2014/10/30 Javascript
JavaScript中数组成员的添加、删除介绍
2014/12/30 Javascript
JQuery在循环中绑定事件的问题详解
2016/06/02 Javascript
百度地图去掉marker覆盖物或者去掉maker的label文字方法
2018/01/26 Javascript
Vue利用canvas实现移动端手写板的方法
2018/05/03 Javascript
cnpm加速Angular项目创建的方法
2018/09/07 Javascript
Angular事件之不同组件间传递数据的方法
2018/11/15 Javascript
解决echarts数据二次渲染不成功的问题
2020/07/20 Javascript
Python中强大的命令行库click入门教程
2016/12/26 Python
python遍历一个目录,输出所有的文件名的实例
2018/04/23 Python
深入理解Python中的 __new__ 和 __init__及区别介绍
2018/09/17 Python
浅析python中的迭代与迭代对象
2018/10/08 Python
Python Django框架模板渲染功能示例
2019/11/08 Python
Pycharm-community-2020.2.3 社区版安装教程图文详解
2020/12/08 Python
英国最大的LED专业零售商:Led Hut
2018/03/16 全球购物
上班打牌检讨书
2014/02/07 职场文书
2014年大学生党课心得体会范文
2014/03/29 职场文书
绿色环保演讲稿
2014/05/10 职场文书
社区平安建设方案
2014/05/25 职场文书
民生工作实施方案
2014/05/31 职场文书
校本教研活动总结
2014/07/01 职场文书
总经理岗位职责说明书
2014/07/30 职场文书
学校运动会广播稿
2014/10/11 职场文书
人事主管岗位职责
2015/02/04 职场文书
2015年实习班主任工作总结
2015/04/23 职场文书
交通肇事罪辩护词
2015/05/21 职场文书
业务员年终工作总结2015
2015/05/28 职场文书
陪护人员误工证明
2015/06/24 职场文书
2016年119消防宣传日活动总结
2016/04/05 职场文书
Windows Server 2012 R2服务器安装与配置的完整步骤
2022/07/15 Servers