源码地址 https://github.com/tencentmusic/cube-studio/tree/master/aihub/deep-learning/face-paint/web

实现过程 将个人头像人体人脸识别,裁剪出肩膀以上部分,并将图片进行卡通化处理,最后与背景图片和文字合成,效果如下


实现代码:

import argparse
import base64
import datetime
import os
import sysimport cv2
import numpy as np
from tqdm import tqdm
import pysnooper
from PIL import ImageFont
from PIL import Image
from PIL import ImageDrawfrom paddleseg.utils import get_sys_env, logger, get_image_listfrom infer import Predictorimport os
import dlib
import collections
from typing import Union, List
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import torchdef get_bg_img(bg_img_path, img_shape):if bg_img_path is None:bg = 255 * np.ones(img_shape)elif not os.path.exists(bg_img_path):raise Exception('The --bg_img_path is not existed: {}'.format(bg_img_path))else:bg = cv2.imread(bg_img_path)return bgdef makedirs(save_dir):dirname = save_dir if os.path.isdir(save_dir) else \os.path.dirname(save_dir)if not os.path.exists(dirname):os.makedirs(dirname)@pysnooper.snoop()
def seg_image(args):assert os.path.exists(args['img_path']), \"The --img_path is not existed: {}.".format(args['img_path'])logger.info("Input: image")logger.info("Create predictor...")predictor = Predictor(args)logger.info("Start predicting...")img = cv2.imread(args['re_save_path'])bg_img = get_bg_img(args['bg_img_path'], img.shape)out_img = predictor.run(img, bg_img)# print(type(out_img))cv2.imwrite(args['save_path'], out_img)img_draw_text = Image.open(args['save_path'])draw = ImageDraw.Draw(img_draw_text)x,y = img_draw_text.sizeft = ImageFont.truetype("/home/ubuntu/PaddleSeg-release-2.6/contrib/PP-HumanSeg/src/1.ttf", args['text_height'])draw.text(args['text_position'], args['text'], font=ft, fill=args['text_color'])file = open(args['save_path'], 'rb')base64_str = base64.b64encode(file.read()).decode('utf-8')print(len(base64_str))return base64_str# img_ = Image.open(out_img)# print(img_)def get_dlib_face_detector(predictor_path: str = "shape_predictor_68_face_landmarks.dat"):if not os.path.isfile(predictor_path):model_file = "shape_predictor_68_face_landmarks.dat.bz2"os.system(f"wget http://dlib.net/files/{model_file}")os.system(f"bzip2 -dk {model_file}")detector = dlib.get_frontal_face_detector()shape_predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')def detect_face_landmarks(img: Union[Image.Image, np.ndarray]):if isinstance(img, Image.Image):img = np.array(img)faces = []dets = detector(img)for d in dets:shape = shape_predictor(img, d)faces.append(np.array([[v.x, v.y] for v in shape.parts()]))return facesreturn detect_face_landmarksdef display_facial_landmarks(img: Image,landmarks: List[np.ndarray],fig_size=[15, 15]
):plot_style = dict(marker='o',markersize=4,linestyle='-',lw=2)pred_type = collections.namedtuple('prediction_type', ['slice', 'color'])pred_types = {'face': pred_type(slice(0, 17), (0.682, 0.780, 0.909, 0.5)),'eyebrow1': pred_type(slice(17, 22), (1.0, 0.498, 0.055, 0.4)),'eyebrow2': pred_type(slice(22, 27), (1.0, 0.498, 0.055, 0.4)),'nose': pred_type(slice(27, 31), (0.345, 0.239, 0.443, 0.4)),'nostril': pred_type(slice(31, 36), (0.345, 0.239, 0.443, 0.4)),'eye1': pred_type(slice(36, 42), (0.596, 0.875, 0.541, 0.3)),'eye2': pred_type(slice(42, 48), (0.596, 0.875, 0.541, 0.3)),'lips': pred_type(slice(48, 60), (0.596, 0.875, 0.541, 0.3)),'teeth': pred_type(slice(60, 68), (0.596, 0.875, 0.541, 0.4))}fig = plt.figure(figsize=fig_size)ax = fig.add_subplot(1, 1, 1)ax.imshow(img)ax.axis('off')for face in landmarks:for pred_type in pred_types.values():ax.plot(face[pred_type.slice, 0],face[pred_type.slice, 1],color=pred_type.color, **plot_style)plt.show()import PIL.Image
import PIL.ImageFile
import numpy as np
import scipy.ndimagedef align_and_crop_face(img: Image.Image,landmarks: np.ndarray,expand: float = 1.0,output_size: int = 1024,transform_size: int = 4096,enable_padding: bool = True,
):# Parse landmarks.# pylint: disable=unused-variablelm = landmarkslm_chin = lm[0: 17]  # left-rightlm_eyebrow_left = lm[17: 22]  # left-rightlm_eyebrow_right = lm[22: 27]  # left-rightlm_nose = lm[27: 31]  # top-downlm_nostrils = lm[31: 36]  # top-downlm_eye_left = lm[36: 42]  # left-clockwiselm_eye_right = lm[42: 48]  # left-clockwiselm_mouth_outer = lm[48: 60]  # left-clockwiselm_mouth_inner = lm[60: 68]  # left-clockwise# Calculate auxiliary vectors.eye_left = np.mean(lm_eye_left, axis=0)eye_right = np.mean(lm_eye_right, axis=0)eye_avg = (eye_left + eye_right) * 0.5eye_to_eye = eye_right - eye_leftmouth_left = lm_mouth_outer[0]mouth_right = lm_mouth_outer[6]mouth_avg = (mouth_left + mouth_right) * 0.5eye_to_mouth = mouth_avg - eye_avg# Choose oriented crop rectangle.x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1]x /= np.hypot(*x)x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8)x *= expandy = np.flipud(x) * [-1, 1]c = eye_avg + eye_to_mouth * 0.1quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y])qsize = np.hypot(*x) * 2# Shrink.shrink = int(np.floor(qsize / output_size * 0.5))if shrink > 1:rsize = (int(np.rint(float(img.size[0]) / shrink)), int(np.rint(float(img.size[1]) / shrink)))img = img.resize(rsize, PIL.Image.ANTIALIAS)quad /= shrinkqsize /= shrink# Crop.border = max(int(np.rint(qsize * 0.1)), 3)crop = (int(np.floor(min(quad[:, 0]))), int(np.floor(min(quad[:, 1]))), int(np.ceil(max(quad[:, 0]))),int(np.ceil(max(quad[:, 1]))))crop = (max(crop[0] - border, 0), max(crop[1] - border, 0), min(crop[2] + border, img.size[0]),min(crop[3] + border, img.size[1]))if crop[2] - crop[0] < img.size[0] or crop[3] - crop[1] < img.size[1]:img = img.crop(crop)quad -= crop[0:2]# Pad.pad = (int(np.floor(min(quad[:, 0]))), int(np.floor(min(quad[:, 1]))), int(np.ceil(max(quad[:, 0]))),int(np.ceil(max(quad[:, 1]))))pad = (max(-pad[0] + border, 0), max(-pad[1] + border, 0), max(pad[2] - img.size[0] + border, 0),max(pad[3] - img.size[1] + border, 0))if enable_padding and max(pad) > border - 4:pad = np.maximum(pad, int(np.rint(qsize * 0.3)))img = np.pad(np.float32(img), ((pad[1], pad[3]), (pad[0], pad[2]), (0, 0)), 'reflect')h, w, _ = img.shapey, x, _ = np.ogrid[:h, :w, :1]mask = np.maximum(1.0 - np.minimum(np.float32(x) / pad[0], np.float32(w - 1 - x) / pad[2]),1.0 - np.minimum(np.float32(y) / pad[1], np.float32(h - 1 - y) / pad[3]))blur = qsize * 0.02img += (scipy.ndimage.gaussian_filter(img, [blur, blur, 0]) - img) * np.clip(mask * 3.0 + 1.0, 0.0, 1.0)img += (np.median(img, axis=(0, 1)) - img) * np.clip(mask, 0.0, 1.0)img = PIL.Image.fromarray(np.uint8(np.clip(np.rint(img), 0, 255)), 'RGB')quad += pad[:2]# Transform.img = img.transform((transform_size, transform_size), PIL.Image.QUAD, (quad + 0.5).flatten(), PIL.Image.BILINEAR)if output_size < transform_size:img = img.resize((output_size, output_size), PIL.Image.ANTIALIAS)return imgimport pysnooper
@pysnooper.snoop()
def start(config=r'/home/ubuntu/PaddleSeg-release-2.6/contrib/PP-HumanSeg/src/inference_models/portrait_pp_humansegv2_lite_256x144_inference_model_with_softmax/deploy.yaml',img_path=r'/home/ubuntu/PaddleSeg-release-2.6/contrib/PP-HumanSeg/src/data/images/1.jpg',re_save_path=r'temp/1_.jpg',save_path=r'temp/1.jpg',text='陈',use_gpu=False,test_speed=False, use_optic_flow=False, use_post_process=False):args = {'config': config,'img_path': img_path,'re_save_path': re_save_path,'save_path': save_path,'use_gpu': use_gpu,'test_speed': test_speed,"text":text,'use_optic_flow': use_optic_flow,'use_post_process': use_post_process}print(type(args))# 先动漫化后增加背景效果更佳# 加载网络或本地文件save_ = datetime.datetime.now().strftime('%Y%m%d%H%M%S')os.mkdir(save_)device = "cuda" if torch.cuda.is_available() else "cpu"model = torch.hub.load("bryandlee/animegan2-pytorch:main", "generator", device=device).eval()face2paint = torch.hub.load("bryandlee/animegan2-pytorch:main", "face2paint", device=device, side_by_side=True)img = Image.open(args['img_path']).convert("RGB")# img = Image.open("/content/sample.jpg").convert("RGB")face_detector = get_dlib_face_detector()landmarks = face_detector(img)out = ''for landmark in landmarks:face = align_and_crop_face(img, landmark, expand=1.3)p_face = face2paint(model=model, img=face, size=512)# display(p_face)p_face.save('temp/input_cartoon.jpg') # 此输出为对比图片# 裁剪为需要的部分输出x_, y_ = p_face.sizeout = p_face.crop((int(x_/2), 0, x_, y_))  # 后面一半是卡通效果图img_ = outx, y = img_.sizeprint(x, y)all_list = []all_backgroud=[{"path":"icon/1.jpg","position":[410,260],"height":340,"text_position":(260,200),"text_height":200,"color":(149,6,2),"text_color": "white"},{"path": "icon/2.jpg","position": [70, 200],"height": 380,"text_position": (450, 300),"text_height": 180,"color": (182,28,30),"text_color": "white"},{"path": "icon/3.jpg","position": [330, 150],"height": 370,"text_position": (150, 350),"text_height": 150,"color": (114,10,11),"text_color": "white"},{"path": "icon/4.jpg","position": [350, 270],"height": 340,"text_position": (140, 400),"text_height": 150,"color": (152, 16, 0),"text_color": "white"},{"path": "icon/5.jpg","position": [260, 230],"height": 570,"text_position": (80, 430),"text_height": 180,"color": (240, 105, 116),"text_color": "white"},{"path": "icon/6.jpg","position": [100, 230],"height": 320,"text_position": (460, 310),"text_height": 170,"color": (194, 0, 8),"text_color": "white"},{"path": "icon/7.jpg","position": [240, 210],"height": 400,"text_position": (130, 290),"text_height": 140,"color": (244, 214, 190),"text_color": "white"},{"path": "icon/8.jpg","position": [120, 190],"height": 330,"text_position": (460, 325),"text_height": 150,"color": (216, 18, 19),"text_color": "white"},{"path": "icon/9.jpg","position": [380, 260],"height": 400,"text_position": (90, 330),"text_height": 185,"color": (250, 250, 250),"text_color": "red"},{"path": "icon/10.jpg","position": [100, 200],"height": 320,"text_position": (410, 290),"text_height": 180,"color": (250, 250, 250),"text_color": "red"}]for pic in all_backgroud:img_=img_.resize((int((pic['height']/y)*x),pic['height']),Image.ANTIALIAS)newIm = Image.new('RGB', (800, 800), pic['color'])newIm.paste(img_, pic['position'])  # 把人体复制进去newIm.save(args['re_save_path'])args['bg_img_path']=pic['path']args['position']=pic['position']args['height']=pic['height']args['text_position']=pic['text_position']args['text_height']=pic['text_height']args['text_color'] = pic['text_color']base64_ = seg_image(args)all_list.append(base64_)return all_listif __name__ == "__main__":image_path = r'/home/ubuntu/PaddleSeg-release-2.6/contrib/PP-HumanSeg/src/data/images/human.jpg'file_after = open(image_path, 'rb')base64_after_str = base64.b64encode(file_after.read()).decode('utf-8')print(len(base64_after_str))imgdata = base64.b64decode(base64_after_str)# 将图片保存为文件if os.path.exists('temp'):passelse:os.mkdir('temp')name_ = datetime.datetime.now().strftime('%Y%m%d%H%M%S')new_image_path = f'temp/{name_}.jpg'with open(new_image_path, 'wb') as f:f.write(imgdata)start(# config=r'E:\PaddleSeg-release-2.6\contrib\PP-HumanSeg\src\inference_models\portrait_pp_humansegv2_lite_256x144_inference_model_with_softmax\deploy.yaml',img_path=new_image_path,# bg_img_path=r'E:\PaddleSeg-release-2.6\contrib\PP-HumanSeg\src\data\images\bg_1.jpg',# re_save_path=r'E:\PaddleSeg-release-2.6\contrib\PP-HumanSeg\src\data\images\_1.jpg',# save_path=r'E:\PaddleSeg-release-2.6\contrib\PP-HumanSeg\src\data\images_result\1.jpg',# use_gpu=True,# test_speed=False, use_optic_flow=False, use_post_process=False))

详情参考github中aihub功能:https://github.com/tencentmusic/cube-studio/tree/master/aihub/deep-learning/face-paint

ai个性化 国庆 头像 合成相关推荐

  1. 祖国生日快乐,个性化国庆头像合成

    在线直达地址: https://www.iloveimg.com/zh-cn/photo-editor 每逢节日,都会有一堆小工具刷屏,为用户头像加装饰,这些小工具,大多需要微信授权登录,收集用户信息 ...

  2. 微信小程序个性头像、国庆头像、新年头像、圣诞头像等合成

    微信小程序个性头像.国庆头像.新年头像.圣诞头像等合成 先看一下,整体效果,搜索微信小程序<我i头像> 微信小程序生成国庆头像工具,祝大家国庆快乐#国庆 1 操作与对应技术点 1 用 ca ...

  3. 国庆头像小程序源码,带独立版后台同时可添加小程序跳转+流量主,所有改动均可后台添加+带搭建教程

    微信小程序实现国旗头像,国庆个性化头像 国庆头像小程序源码,带独立版后台同时可添加小程序跳转+流量主,所有改动均可后台添加+带搭建教程 快去挑选一个自己喜欢的国庆头像吧,只需简单两步即可制作自己专属国 ...

  4. 国庆头像html代码

    每年国庆节都会发现自己的好友头像加特效了,其实这种网站代码很简单,就是一个html单页替换下头像框就可以了. <html lang="en"> <head> ...

  5. 2022国庆头像小程序最新可用源码

    正文: 实测搭建成功,功能没问题,明天国庆节了,可以提前布局了. 云开发国庆头像生成器,完整版,附带流量主接口,开发工具打开即可,需要添加合法域名,教程我都放文档里了,小白都能搭建,类目选择信息查询. ...

  6. 2022国庆头像制作iAPP安卓源码+附APP成品

    正文: 测试机型:安卓11系统,还在为没有办法制作国庆头像而担心吗,有这个这个头像制作器,就不用担心了,有源码,如果不需要源码直接用成品即可. 程序: wwgefu.lanzoub.com/iJNAU ...

  7. 【多功能小程序】古风姓氏圣诞国庆头像生成小程序源码

    多功能生成头像小程序 姓氏头像 圣诞头像 国庆头像 形状头像 公式头像 下载地址:

  8. IM多人聊天-群聊头像合成方法

    IM多人聊天群聊头像合成方法 群聊中将多个成员的头像合成为群聊的头像: ViewController.m // // ViewController.m // imageMerge // // Crea ...

  9. vue h5分享微信节日头像合成”

    9月24日,微信头像合成爆红,公司为了趁热点,也要做一个类似的功能,于是利用canvas也做了一个 ,其实很简单直接上代码 <div id="app"><div ...

最新文章

  1. 用计算机写作ppt文库,[百度文库.ppt
  2. 初等数学O 集合论基础 第六节 商集
  3. ICML 2020 | 第四范式基于AutoML的深度网络记忆性自动化挖掘
  4. python学习网址
  5. vue-router和react-router嵌套路由layout配置方案的区别
  6. 前端:实现手机左右滑动效果
  7. 基于Android的智能家居手持终端系统开发(毕设开题报告)修改版
  8. Java判断字符串的数字类型(小数、整数)
  9. MPLS解决路由黑洞实验分析(华为设备)
  10. Invalid maximum heap size: -Xmx
  11. Visual Studio 2013官方简体中文专业版/旗舰版/高级版下载(含激活序列号)
  12. windows 10 Tera Term显示乱码
  13. 如何破解好友QQ空间加密.查看最新日志
  14. AMD显卡怎么设置玩游戏更流畅
  15. html内外边距区别,css水平边距和垂直边距 css中的内边距和外边距?
  16. 是的,你的AI技能正在“贬值”
  17. FreeRTOS学习,适用于FreeRTOS初学者,FreeRTOS整体知识框架
  18. android加固之后出问题,Android 应用加固
  19. mysql远程访问的设置
  20. leetcode买卖股票问题(思路、方法、code)

热门文章

  1. android系统优化排行,性能最强的10大安卓手机排行,你用的排第几?
  2. Enterprise Architect入门:如何利用BABOK指南进行建模
  3. 玩转华为数据中心交换机系列 | 汇总
  4. matlab ild,10GBASE-KR
  5. javaweb企业员工考勤管理系统案例
  6. 有关监控的前5名最佳书籍
  7. php自我介绍50字,自我介绍50字
  8. Jtapi开发之转接二 传递uui
  9. 报错:Error creating bean with name ‘serverEndpointExporter‘ defined in class path resource [group/oneo
  10. 基于四旋翼无人机的PD控制研究(Matlab代码实现)