你好陌生人,请不要试图越过权限文章,谢谢!

基于Pillow对证件照批量自动化换底


前言

  今天在群里看到小伙伴们需要批量对班级的同学进行照片换底色,目前市面上网页中存在在线换底色的网站,但是普遍需要收费或者七七八八的条件,搞得很繁琐,所以我就想写一个自动化换底色的程序来试试可不可以实现。

  一看到照片换底,我首先想到的思路就是先想办法把照片的背景抠掉,类似于PS的抠图技巧,然后对目标像素点进行填充,重新生成新的图片保存就可以。

开发

照片抠图

  一张证件照,可以简单的分为底色和人像,所以我搜索了一下,发现了一个库paddlehub中有一个 deeplabv3p_xception65_humanseg模型,是图像分割,已经训练完毕,我直接采用,然后试着对图像进行抠图,然后~,就出现了这种情况。

  很尬尴,图像全部反了,我调试了半天没整出来,知道了大概的原理,我就试着找找有没有已经做的比较好的抠图模型让我直接用,于是乎,我发现了这个宝藏——在线抠图网站,很像,抠图的效果还不错,大概是这样,由于隐私问题我打了马赛克,他的背景图已经被抠掉了,有官方文档,直接使用,但是每个月只有50次免费机会,不过足够使用啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#抠图
def imageClipping(path):
try:
old = './photo/' + path
new = './temporary/' + path[:-4] + '.png'
response = requests.post(
'https://api.remove.bg/v1.0/removebg',
files={'image_file': open(old, 'rb')},
data={'size': 'auto'},
headers={'X-Api-Key': 'D4kSvWb14svjr6xUHUA7m7po'},
)
if response.status_code == requests.codes.ok:
with open(new, 'wb') as out:
out.write(response.content)
return 'success'
else:
#状态码为402时没有余额
print("Error:", response.status_code, response.text)
return 'error'
except:
return 'error

基于图片的灰度化处理及上色

  抠好的图保存到自己指定的路径中,然后就可以给图片上色了,我们使用Pillow对图片上色,对于已经抠好的图,可以指定不同颜色进行上色。

1
2
3
4
5
6
7
8
9
color = 'red'
#打开图片
no_bg_image = Image.open(no_bg_image_path)#图片路径
#获取宽高
x, y = no_bg_image.size
#对图片进行RGB处理,新建一个图层为红色
new_image = Image.new('RGBA', no_bg_image.size, color=color)
#下面的操作是粘贴人像,抠图后的图片直接放置到红色背景图片上
new_image.paste(no_bg_image, (0, 0, x, y), no_bg_image)

  给他们打上浓浓的马赛克认不出来了吧,这是对已经抠像的图片进行的上色处理,颜色可以自己调整,非常方便。

运行程序

  运行的程序部分截图,可以进行批量化的操作


  完整的程序运行效果:

  程序完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import os
from PIL import Image
import requests
import time
import json

#获取目标所有图片,并完成转化
def get_image():
global password_count
password_count = 0
with open('./config.json') as file_json:
config=json.load(file_json)
for item in os.listdir('./photo'):
print("----正在裁剪[%s]背景色----"%(item))
for items in config['data']:
if (items['status'] == 1):
password_count += 1
else:
break
res=imageClipping(item,config['data'][password_count]['password'])
if res == 'success':
print("[%s]裁剪成功"%(item))
os.remove('./photo/'+item)
else:
print("[%s]裁剪失败"%(item))
time.sleep(1)

#抠图
def imageClipping(path,password):
try:
old = './photo/' + path
new = './temporary/' + path[:-4] + '.png'

response = requests.post(
'https://api.remove.bg/v1.0/removebg',
files={'image_file': open(old, 'rb')},
data={'size': 'auto'},
headers={'X-Api-Key': password},
)
if response.status_code == requests.codes.ok:
with open(new, 'wb') as out:
out.write(response.content)
return 'success'
else:
#状态码为402时没有余额
print("Error:", response.status_code, response.text)
return 'error'
except:
return 'error'


#更换底色
def replaceImage(color = 'red'):
for item in os.listdir('./temporary'):
try:
no_bg_image_path = './temporary/'+item
no_bg_image = Image.open(no_bg_image_path)
x, y = no_bg_image.size
new_image = Image.new('RGBA', no_bg_image.size, color=color)
new_image.paste(no_bg_image, (0, 0, x, y), no_bg_image)
new_image.save('./new_photo/'+item)
print("[%s]换底成功,颜色变更为:[%s]"%(item,color))
except:
print("[%s]换底失败" % (item))
continue

print("--------------照片已完成转换---------")


def main(color):
get_image()
print("图像已裁剪完成,正在更换目标底色")
replaceImage(color)

if __name__ == '__main__':
with open('./config.json') as file_json:
config=json.load(file_json)
print(config['data'][0])
while(1):
print("""
------------------自动化证件照底色更换工具---------------------
------------------ 作者:小健 ----------------------
------------------ 注意事项 ----------------------
------------请将需要更换的图片放置[photo]文件夹中---------------
------------生成后的图片位置:[new_photo]文件夹中----------------
------------抠图后的人像文件位于:[temporary]文件夹--------------
------------如需需要,则保存,否则建议删除 ---------------------
""")
item = input("1.照片底色更换 2.清空temporary\n")
if(item == '1'):
while(1):
color = input("输入选项需要的底色:1.红色 2.蓝色 3.白色 4.上一级\n")
if(color == '1'):
main('red')
break
elif(color == '2'):
main('blue')
break
elif(color == '3'):
main('white')
break
elif(color == '4'):
break
else:
print("输入有误,请重新选择")
continue


结尾

  写完运行的效果还不错,在几分钟内就可以完成近百张的图像底色更换,代码比较粗糙,可以继续优化、在线化、自动化及桌面化,所以我懒死了,后续有空在调整吧,得去刷网课了。

  代码已上传Github:证件照、图像化的自动化换色

  欢迎技术交流沟通!