利用机器学习完成动漫人脸识别与贴图

一、引言

这只是我随意做的一段小脚本而已,功能是检测动漫人物的人脸,并在指定位置替换上自己预备好的贴图。
机器学习的原理我几乎一窍不通,全程只是普通地调库,没什么特别的技术含量。

代码主要借助了 python Anime Face Detector库(点击此处跳转)中动漫人脸识别的功能,这个库可以很方便地标记动漫人脸的特征点,之后手动将预设的贴图在指定位置贴上去就行了。

所有代码我都上传到我的 gitee 仓库了,需要的可以去下载:https://gitee.com/oldprincess/xiaoxile

二、代码

2.1 环境配置

我使用的是 python 3.7,首先需要安装库Anime Face Detector
这个库安装前需要下载许多依赖库,例如torchopencv-python等等,所以可能会有些久(我使用清华的镜像源花了15分钟左右)

pip install anime-face-detector

在代码运行时还需要对应的模型文件,它会自动下载,也可以手动去 github 上下载库Anime Face Detector作者提供的模型文件(点击此处跳转),此处需要的文件只有mmdet_anime-face_yolov3.pthmmpose_anime-face_hrnetv2.pth

模型文件应放置在 <当前工作目录>\checkpoints\目录下

2.2 需要import的库

import torch import pathlib import cv2 import math from anime_face_detector import create_detector

torchpathlib只是用于修改模型的默认路径,在默认情况下它会位于C:\User\<用户名>\.cache\torch\hub处(在我的机器上是这个路径),此处将其修改为当前的工作目录

cv2用于进行图像读取和处理,包括缩放、旋转等等,math库用于根据特征点坐标计算旋转角度,而anime_face_detector就是识别器

2.3 全局设定

# set torch.hub dir torch.hub.set_dir(str(pathlib.Path().cwd())) MOUTH_DOT = [24, 25, 26, 27] # mouth key dot LEFT_FACE, RIGHT_FACE = 1, 3 # face key dot detector = create_detector(device='cpu') # init detector smile = cv2.imread('smile.png', cv2.IMREAD_UNCHANGED) # load smile pic

第一行将 torch 的路径设置为当前的工作目录
接下来的 MOUTH_DOTLEFT_FACERIGHT_FACE 是特征点的索引,分别是 4 个嘴部特征脸,左脸,右脸
之后的 detector 创建了一个识别器,因为我的电脑并没有配置 cuda 环境,所以 device 参数设置为 cpu
之后将事先准备好的 smile.png 读入

2.4 函数

此处是主要的处理函数 paste_smile,即识别图片中的脸部,并在对应坐标贴图

使用一个 3 通道的 img 图片为输入,首先使用之前初始化的识别器产生识别结果 preds,它包含多个面部的特征点信息,其中的 keypoints 就是特征点(坐标为浮点数)

对嘴巴的 4 个特征点,通过计算均值确定坐标;而对于脸部的特征点,直接采用对应的结果

def paste_smile(img): preds = detector(img) # detector anime face # every face in img for pred in preds: dots = pred['keypoints'] # key dots # average mouth dot pos mouth = ( int(sum([dots[i][0] for i in MOUTH_DOT]) // 4), int(sum([dots[i][1] for i in MOUTH_DOT]) // 4) ) # mouth dot # face dots, pos[0] is width, pos[1] is height l_face = (int(dots[LEFT_FACE][0]), int(dots[LEFT_FACE][1])) # left face dot r_face = (int(dots[RIGHT_FACE][0]), int(dots[RIGHT_FACE][1])) # right face dot

接着,需要对读入的图片进行缩放与旋转处理。计算面部宽度face_width,之后的图片宽度使用人物面部宽度一半

face_width = abs(l_face[0] - r_face[0]) # calculate face size # resize smile pic ratio = 0.5 * (face_width / smile.shape[1]) # shape = (height, width, ...) img2 = cv2.resize(smile, (int(smile.shape[1] * ratio), int(smile.shape[0] * ratio))) img2_height, img2_width, _ = img2.shape # shape = (height, width, ...)

接着,对图片进行旋转。如果左右侧脸的高度不一致,那么就对贴图进行旋转,通过atan函数计算出旋转角

# rotate pic if l_face[0] != r_face[0]: # calculate angle theta = - math.atan((r_face[1] - l_face[1]) / (r_face[0] - l_face[0])) / math.pi * 180 # rotate smile matrix = cv2.getRotationMatrix2D((img2_width // 2, img2_height // 2), theta, 1.0) img2 = cv2.warpAffine(img2, matrix, (img2_width, img2_height))

最后,进行图片贴图。获取贴图透明通道的信息,将非透明部分贴到原图中

# copy smile alpha = img2[:, :, 3] # alpha channel for w in range(img2_width): for h in range(img2_height): if alpha[h, w] != 0: s_h = mouth[1] - (img2_height // 2) + h # pos height s_w = mouth[0] - (img2_width // 2) + w # pos width if (0 <= s_h < img.shape[0]) and (0 <= s_w < img.shape[1]): img[s_h, s_w, 0:3] = img2[h, w, 0:3] return img

2.5 demo

此处将上述代码作为 xiaoxile 模块,使用时,只需要 import 并调用其 paste_smile 函数即可

import xiaoxile import cv2 img = cv2.imread('pic.jpg') img2 = xiaoxile.paste_smile(img) cv2.imshow('', img2) cv2.waitKey()

__EOF__

本文作者kentle
本文链接https://www.cnblogs.com/kentle/p/16208480.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   kentle  阅读(1202)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示