有趣的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下载文件时显示下载进度的方法
Apr 02 Python
Python PyAutoGUI模块控制鼠标和键盘实现自动化任务详解
Sep 04 Python
对python添加模块路径的三种方法总结
Oct 16 Python
python 执行文件时额外参数获取的实例
Dec 18 Python
详解python中的数据类型和控制流
Aug 08 Python
用Python抢火车票的简单小程序实现解析
Aug 14 Python
安装Pycharm2019以及配置anconda教程的方法步骤
Nov 11 Python
6行Python代码实现进度条效果(Progress、tqdm、alive-progress​​​​​​​和PySimpleGUI库)
Jan 06 Python
TensorFlow自定义损失函数来预测商品销售量
Feb 05 Python
pytorch掉坑记录:model.eval的作用说明
Jun 23 Python
Matplotlib中%matplotlib inline如何使用
Jul 28 Python
Python3+Appium安装及Appium模拟微信登录方法详解
Feb 16 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
ThinkPHP实现跨模块调用操作方法概述
2014/06/20 PHP
PHP图片自动裁切应付不同尺寸的显示
2014/10/16 PHP
PHP实现通过正则表达式替换回调的内容标签
2015/06/15 PHP
Centos 6.5下PHP 5.3安装ffmpeg扩展的步骤详解
2017/03/02 PHP
javascript 写类方式之七
2009/07/05 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
仿微博字符限制效果实现代码
2012/04/20 Javascript
Javascript连接多个数组不用concat来解决
2014/03/24 Javascript
基于jQuery插件实现环形图标菜单旋转切换特效
2015/05/15 Javascript
详解页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
2015/12/03 Javascript
JavaScript encodeURI 和encodeURIComponent
2015/12/04 Javascript
JS+HTML5实现图片在线预览功能
2017/07/22 Javascript
JavaScript事件处理程序详解
2017/09/19 Javascript
layui使用label标签的方法
2019/09/14 Javascript
高性能js数组去重(12种方法,史上最全)
2019/12/21 Javascript
jQuery实现点击滚动到指定元素上的方法分析
2020/03/19 jQuery
用Nodejs实现在终端中炒股的实现
2020/10/18 NodeJs
[36:20]KG vs SECRET 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Selenium元素的常用操作方法分析
2018/08/10 Python
简单了解python的内存管理机制
2019/07/08 Python
Python流程控制 if else实现解析
2019/09/02 Python
使用keras实现BiLSTM+CNN+CRF文字标记NER
2020/06/29 Python
Python如何合并多个字典或映射
2020/07/24 Python
Python Opencv图像处理基本操作代码详解
2020/08/31 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
Python爬虫之Selenium警告框(弹窗)处理
2020/12/04 Python
Python基于opencv的简单图像轮廓形状识别(全网最简单最少代码)
2021/01/28 Python
CSS3实现滚动条动画效果代码分享
2016/08/03 HTML / CSS
css3 column实现卡片瀑布流布局的示例代码
2018/06/22 HTML / CSS
轻松制作精彩视频:Animoto
2018/09/19 全球购物
Crocs波兰官方商店:女鞋、男鞋、童鞋、洞洞鞋
2019/10/08 全球购物
残疾人创业典型事迹
2014/02/01 职场文书
节水口号标语
2014/06/19 职场文书
小学三年级作文之写景
2019/11/05 职场文书
idea编译器vue缩进报错问题场景分析
2021/07/04 Vue.js
如何让你的Nginx支持分布式追踪详解
2022/07/07 Servers