让Serverless为你的头像增加点装饰
目录
无论是国庆还是新年,经常会有一个平台为我们提供一个生成头像的小工具,很是新奇好玩,这类平台/工具,一般都有两个方法给我们制作头像。
- 直接加装饰,例如外面加一个框框,下面加一个logo等;
- 通过一些机器学习算法,增加一些装饰,例如增加一个圣诞帽等;
Serverless直接增加头像装饰
其实这个功能很简单,主要功能就是选择一个图片,上传自己的头像,然后函数部分进行图像的合成,这一部分并没有涉及到机器学习算法,仅仅是图像合成相关算法。
主要通过用户上传的图片,在指定位置增加预定图片/用户选择的图片作为装饰物进行添加,添加过程是:
将预定图片/用户选择的图片进行美化,此处仅是将其变成圆形:
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
31def do_circle(base_pic):
icon_pic = Image.open(base_pic).convert("RGBA")
icon_pic = icon_pic.resize((500, 500), Image.ANTIALIAS)
icon_pic_x, icon_pic_y = icon_pic.size
temp_icon_pic = Image.new('RGBA', (icon_pic_x + 600, icon_pic_y + 600), (255, 255, 255))
temp_icon_pic.paste(icon_pic, (300, 300), icon_pic)
ima = temp_icon_pic.resize((200, 200), Image.ANTIALIAS)
size = ima.size
# 因为是要圆形,所以需要正方形的图片
r2 = min(size[0], size[1])
if size[0] != size[1]:
ima = ima.resize((r2, r2), Image.ANTIALIAS)
# 最后生成圆的半径
r3 = 60
imb = Image.new('RGBA', (r3 * 2, r3 * 2), (255, 255, 255, 0))
pima = ima.load() # 像素的访问对象
pimb = imb.load()
r = float(r2 / 2) # 圆心横坐标
for i in range(r2):
for j in range(r2):
lx = abs(i - r) # 到圆心距离的横坐标
ly = abs(j - r) # 到圆心距离的纵坐标
l = (pow(lx, 2) + pow(ly, 2)) ** 0.5 # 三角函数 半径
if l < r3:
pimb[i - (r - r3), j - (r - r3)] = pima[i, j]
return imb添加该装饰到用户头像上:
1
2
3
4
5
6
7
8
9
10
11
12
13def add_decorate(base_pic):
try:
base_pic = "./base/%s.png" % (str(base_pic))
user_pic = Image.open("/tmp/picture.png").convert("RGBA")
temp_basee_user_pic = Image.new('RGBA', (440, 440), (255, 255, 255))
user_pic = user_pic.resize((400, 400), Image.ANTIALIAS)
temp_basee_user_pic.paste(user_pic, (20, 20))
temp_basee_user_pic.paste(do_circle(base_pic), (295, 295), do_circle(base_pic))
temp_basee_user_pic.save("/tmp/output.png")
return True
except Exception as e:
print(e)
return False除此之外,为了方便本地测试,项目增加了
test()
方法,模拟API网关传递的数据: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
47def test():
with open("test.png", 'rb') as f:
image = f.read()
image_base64 = str(base64.b64encode(image), encoding='utf-8')
event = {
"requestContext": {
"serviceId": "service-f94sy04v",
"path": "/test/{path}",
"httpMethod": "POST",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"identity": {
"secretId": "abdcdxxxxxxxsdfs"
},
"sourceIp": "14.17.22.34",
"stage": "release"
},
"headers": {
"Accept-Language": "en-US,en,cn",
"Accept": "text/html,application/xml,application/json",
"Host": "service-3ei3tii4-251000691.ap-guangzhou.apigateway.myqloud.com",
"User-Agent": "User Agent String"
},
"body": "{\"pic\":\"%s\", \"base\":\"1\"}" % image_base64,
"pathParameters": {
"path": "value"
},
"queryStringParameters": {
"foo": "bar"
},
"headerParameters": {
"Refer": "10.0.2.14"
},
"stageVariables": {
"stage": "release"
},
"path": "/test/value",
"queryString": {
"foo": "bar",
"bob": "alice"
},
"httpMethod": "POST"
}
print(main_handler(event, None))
if __name__ == "__main__":
test()为了让函数更有同一个返回规范,此处增加统一返回的函数:
1
2
3
4
5
6
7
8def return_msg(error, msg):
return_data = {
"uuid": str(uuid.uuid1()),
"error": error,
"message": msg
}
print(return_data)
return return_data最后就是函数中涂口函数的写法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import base64, json
from PIL import Image
import uuid
def main_handler(event, context):
try:
print("将接收到的base64图像转为pic")
imgData = base64.b64decode(json.loads(event["body"])["pic"].split("base64,")[1])
with open('/tmp/picture.png', 'wb') as f:
f.write(imgData)
basePic = json.loads(event["body"])["base"]
addResult = add_decorate(basePic)
if addResult:
with open("/tmp/output.png", "rb") as f:
base64Data = str(base64.b64encode(f.read()), encoding='utf-8')
return return_msg(False, {"picture": base64Data})
else:
return return_msg(True, "饰品添加失败")
except Exception as e:
return return_msg(True, "数据处理异常: %s" % str(e))
完成后端图像合成功能,可以制作前端页面:
1 |
|
完成之后:
1 | new_year_add_photo_decorate: |
完成之后就可以实现头像加装饰的功能,效果如下:
Serverless与人工智能联手增加头像装饰
其实第一种直接加装饰的方法,是可以直接在前端来实现,可以不通过后端功能实现,既然用到了后端服务,用到了云函数,那么我们不防将人工智能的方法和Serverless架构结合,共同实现一个增加装饰的小工具,先进行一下效果的预览:
这一功能的主要做法就是,通过人工智能算法(此处是通过Dlib实现),进行人脸的检测:
1 | print("dlib人脸关键点检测器,正脸检测") |
此处做法是,只检测一张脸,检测到即进行返回:
1 | for d in dets: |
在Serverless架构下的完整代码:
1 | import cv2 |
至此,即完成了通过用户上传人物头像进行增加圣诞帽的功能。
总结
Serverless架构毕竟是一个新的技术,或者说是一个比较新的Framework,如果刚开始就通过它来做一些很重的产品,可能会让学习者失去兴趣,但是前期可以通过Serverless架构不断的实现一些有趣的功能,小的应用,例如监控告警、图像识别、图像压缩、图像合成、文本摘要、关键词提取、简单的MapReduce等,通过这些小的应用,一方面可以让我们更加深入了解Serverless架构,另一方面也可以让我们对Serverless的实际应用和价值产生更大的信心。
传统情况下,我们如果要做这样的一个工具,可能需要一个服务器,哪怕没有人使用,也要有一台服务器苦苦支撑,那么仅仅就是一个Demo,也要无时无刻的支出成本,但是在Serverless架构下,通过Serverless弹性伸缩特点让我们不惧怕高并发,通过Serverless的按量付费模式,让我们不惧怕成本支出。
希望各位可以通过我的抛砖引玉,更加深入的了解Serverless架构。
欢迎您关注我的博客,也欢迎转载该博客,转载请注明本文地址: http://bluo.cn/serverless-tencent-field-practice-photo/ 。有关于Serverless等相关问题欢迎联系我:80902630
微信号 | 抖音号 |