如何使用div拼接头像,生成心形照片墙?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用div拼接头像,生成心形照片墙?相关的知识,希望对你有一定的参考价值。
参考技术A 可以使用最新的css3进行裁切或遮罩。使用div配合css3再结合svg可以实现各种形状的裁切,css3加背景可以实现遮罩效果。
如果需要兼容的话,可以使用第三方插件。
情人节要到了,为你的女友拼一张照片墙吧!
前言
身为程序员,每天陪女友的时间还不如敲键盘的时间多,要想既敲键盘又能够哄好女友,生活中必要的关心还是必不可少的,那么,身为程序员的我们如何去巧妙的哄好自己的女朋友呢?
最终生成效果图如下:本代码同样适用于生成其他照片。
本文编译环境为 Python3.8.5,不同版本略有出入,望见谅。
一、pip安装相关库
本文中需要用到的相关库有:urllib,random,glob,PIL,numpy,cv2,os
若电脑编译环境缺省相关库可使用以下命令安装:
# 豆瓣高速源
pip3 install #相关缺省库# -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
# 中国科技大学高速源
pip3 install #相关缺省库# -i https://pypi.mirrors.ustc.edu.cn/simple/ --trusted-host pypi.mirrors.ustc.edu.cn
# 阿里云
pip3 install #相关缺省库# -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
二、照片准备
首先我们需要准备的是一系列需要进行拼图的照片,将这些照片存放在pictures 文件夹内(注意如果这里的文件夹名称更改了的话在后面代码中也需要更改哦)
可以看到这些照片的命名是五花八门的,所以,我们需要先对这些照片进行规范化处理,在这里我们编写一个脚本文件 rename.py 来辅助我们处理:
# coding = 'utf-8'
import os
def rename(path):
i = 1
'该文件夹下所有的文件(包括文件夹)'
FileList = os.listdir(path)
'遍历所有文件'
for files in FileList:
'原来的文件路径'
oldDirPath = os.path.join(path, files)
'文件扩展名'
fileType = '.jpg'
'新的文件路径'
newDirPath = os.path.join(path, str(i) + fileType)
'重命名'
os.rename(oldDirPath, newDirPath)
i += 1
# 注意这里的path是你的pictures文件夹所在的路径
path = '/home/zq/Documents/excample/pictures'
rename(path)
注意:文件里的 path 是你的 pictures文件夹所在路径,可以右键文件夹,然后属性即可查看。
运行 rename.py ,我们可以看到 pictures 文件夹中的照片被成功的规范命名。
二、图片拼接
接下编写我们的图片拼接脚本,主要思路如下:
1.引入库
import urllib,random, glob
from PIL import Image
import numpy as np
import cv2 as cv
2.变量设置
savepath = '/home/zq/Documents/excample/pictures/' #图片存储位置
resultSavePath = '/home/zq/Documents/excample/result.png' #生成图片存储位置
modePath = '/home/zq/Documents/excample/mode.jpg' #模板存储位置
path_picture_number = glob.glob(savepath + '*.jpg') #获取图片文件夹内图片
# print(path_picture_number)
pictures_count = len(path_picture_number) #图片数量
all_mean_rgbs = [] #存储计算出的所有平均rgb值
注意这里各个路径变量的值每个人的电脑是不同的,具体查看方式依旧是 右键->属性。
3.功能函数
计算图片平均 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 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 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) + '.jpg').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
4.主函数
if __name__ == '__main__':
#存放匹配图片 rgb 信息
for i in range(1,pictures_count + 1):
img = cv.imread(savepath+str(i)+'.jpg')
rgb = meanrbg(img)
all_mean_rgbs.append(rgb)
all_mean_rgbs = list(enumerate(all_mean_rgbs)) #给列表增加一个索引
v = 60; #生成照片的横距
h = 80; #生成照片的竖距
pixel = 20; #像素
mode_split(savepath,modePath,(v,h),pixel) #模板拼接
5.完整代码
完整代码如下:
import urllib,random, glob
from PIL import Image
import numpy as np
import cv2 as cv
savepath = '/home/zq/Documents/excample/pictures/' #头像存储位置
resultSavePath = '/home/zq/Documents/excample/result.png' #结果存储位置
modePath = '/home/zq/Documents/excample/mode.jpg' #模板存储位置
path_picture_number = glob.glob(savepath + '*.jpg') #获取当前文件夹下pictures个数
# print(path_picture_number)
pictures_count = len(path_picture_number) #picture数量
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 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 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) + '.jpg').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__':
#存放匹配图片 rgb 信息
for i in range(1,pictures_count + 1):
img = cv.imread(savepath+str(i)+'.jpg')
rgb = meanrbg(img)
all_mean_rgbs.append(rgb)
all_mean_rgbs = list(enumerate(all_mean_rgbs)) #给列表增加一个索引
v = 60; #生成照片的横距
h = 80; #生成照片的竖距
# 注意这里的 v,h 比值最好为模板照片的比例,这里为 3 :4
pixel = 20; #像素,越高效果越好,但费时
mode_split(savepath,modePath,(v,h),pixel) #模板拼接
运行结果
运行上述代码,运行界面截图如下:
待运行结束,生成图片效果如前言所示。
总结
用 Python 生成的效果和其他专业的 P图软件比起来自然是没得说,但是其强在自动化与并不需要过强的专业技术,作者也是 Python 刚入门,代码中有不足还请各位大佬们评论区指正,觉得有帮助可以收藏点赞加关注,谢谢亲们支持!
本文属作者原创,转载请注明出处:
https://blog.csdn.net/weixin_46584887/article/details/117718969
以上是关于如何使用div拼接头像,生成心形照片墙?的主要内容,如果未能解决你的问题,请参考以下文章