基于dlib人脸关键点定位的图像视频处理工具
利用调参算法调整人脸关键点的定位,使其更加精确,更好的完成我们图像视频处理
1. 项目说明
图像视频处理在计算机视觉中是一个基本但具有挑战性的任务。它旨在提供详细的人脸关键点定位,相当于为每个人脸进行关键点描点。该技术目前被广泛应用于短视频媒体平台、直播等系统领域。以我们选用的“人脸关键点识别”数据集为例,该项目的挑战在于:
1.1 人脸光照条件的不确定性:
不同的场景会有不同的光照等因素,光照的来 源方向、光照强度的不同都影响人脸图像的灰度布局。
1.2 人脸受遮挡的不确定性:
定位出人脸面部的关键区域位置,包括眉毛、眼睛、鼻子、嘴巴、脸部轮廓等和人脸检测类似,由于受到姿态和遮挡等因素的影响。
1.3 人脸关键点算法的设计:
要实现对视频和图像中的人脸的追踪并分析面部表情,来检测畸形面部体征以进行我们图像视频处理。
2. 安装说明
2.1 环境要求
·paddlepaddle >= 2.0.0rc1
·Python >= 3.7
·dlib库的安装(适配于python版本,本文提供3.8版本Python的dlib安装文件)
强烈建议您安装/使用 GPU 版本的 PaddlePaddle。因为人脸关键点定位模型开销很大,当模型运行在 CPU 时可能会出现内存不足。更详细的安装教程请参考 PaddlePaddle 官网
2.2 dlib库安装
1.首先下载文件dlib-19.19.0-cp38-cp38-win_amd64.whl
该文件在文件浏览器下,可以直接下载。
2.将下载的whl文件放到任意的路径下,然后通过命令行进入到该目录下,
然后运行代码:
pip install dlib-19.19.0-cp38-cp38-win_amd64.whl
之后回车安装即可。
2.3 解压数据
项目部分代码在 dingwei.zip 文件中,数据集在 data.zip 文件中,解压到合适路径即可使用。除了压缩包文件中的程序,也可以在在aistudio项目中可以直接查阅作品中对于帽子和嘴巴特效定位处理的代码:
#嘴巴特效:
import cv2 # 图像处理的opencv库
import argparse # 加载解析模块
import os
def hat_face(opt):
# 加载dlib的人脸检测模型
detector = dlib.get_frontal_face_detector()
# 使用opencv中的imread函数,读取需要添加特效的图片
landmark_predictor = dlib.shape_predictor(opt.landmarks_model_path)
# 使用opencv中的imread函数,读取嘴巴的图片
img_hat = cv2.imread(opt.hat_path)
# img_hat = img_hat[:]
# 对图片进行dlib人脸检测,得到检测后的人脸框信息faceRects
# faceRects = detector(img, 0)
# 图片中可能存在多张人脸,依次遍历输出每张人脸的位置信息,并在特定位置,添加嘴巴特效
cap = cv2.VideoCapture(opt.video_path)
force= cv2.VideoWriter_fourcc("X","V","I","D")
out1 = cv2.VideoWriter("output.avi",force,20,(640,480))
frame_id = 0
while cap.isOpened():
try:
# 因为视频采集,每秒可能会采集N帧图片,因此使用read函数,逐帧读取图片
# ret 返回True或Fasle,表示是否读取到图片
# frame 返回读取的图片信息
ret, frame = cap.read()
# 如果ok为false,则采集结束
if not ret:
# 打印输出,提示信息
print("Camera cap over!")
continue
# frame_id加1,便于跳帧
frame_id += 1
if not int(frame_id) % 2 == 0: continue
faceRects = detector(frame)
if len(faceRects) > 0:
for box_info in faceRects:
# dlib检测出的人脸位置信息,为rectangle类型,所以可以通过left()、top()、right()、bottom()提取人脸框左上角的x0,y0,右下角的x1,y1。
x0, y0, width_face, height_face = box_info.left(), box_info.top(), box_info.right() - box_info.left(), box_info.bottom() - box_info.top()
landmarks = landmark_predictor(frame, box_info)
# 获得嘴巴图片的高height_hat,宽width_hat,便于后面控制嘴巴显示的大小
height_hat, width_hat = img_hat.shape[0], img_hat.shape[1]
# 将嘴巴的高度变成,适合检测到的脸型的大小
imgComposeSizeH = int(height_hat / width_hat * width_face)
# 因为嘴巴在脸部上方,当脸部靠近视频顶部,为了保证嘴巴能显示出来,嘴巴的高度默认为脸部到视频上方的距离
if imgComposeSizeH > (y0 + 220):
imgComposeSizeH = (y0 + 220)
# 将嘴巴的图片归一化到适合的宽和高大小,宽度为人脸的宽度,高度为上面调整后的嘴巴高度
imgComposeSize = cv2.resize(img_hat, (width_face, imgComposeSizeH), interpolation=cv2.INTER_NEAREST)
# 为了实现在人脸上方的额头,添加嘴巴特效,只需要将嘴巴贴到额头处即可
# 注意:y0是人脸检测框左上方顶点的y坐标,y0-20,则差不多定位到额头处,再减去imgComposeSizeH,调整后嘴巴的高度
# 即从这个位置开始贴合嘴巴,可以实现人脸嘴巴特效
top = (y0 + 220 - imgComposeSizeH )
# 当人脸太靠近图片上方,通过前一行的计算,有可能为负数,所以当出现这样的情况时,top设置为0
if top <= 0:
top = 0
# 获得调整尺寸后,嘴巴新的高height_hat_new,新的宽width_hat_new
height_hat_new, width_hat_new = imgComposeSize.shape[0], imgComposeSize.shape[1]
small_img_hat = frame[top:top + height_hat_new, x0:x0 + width_hat_new]
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("small_img_hat.jpg",small_img_hat)
# 将嘴巴图像,从RGB彩色图像转换为灰度图像
small_img_hat_gray = cv2.cvtColor(imgComposeSize, cv2.COLOR_RGB2GRAY)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("small_img_hat_gray.jpg", small_img_hat_gray)
# 阈值化处理,将10<像素<255区间的图像抠出来
# 因为背景为黑色,所以阈值设置10到255,即可将嘴巴区域提取出来
ret, mask_hat = cv2.threshold(small_img_hat_gray, 10, 255, cv2.THRESH_BINARY)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("mask_hat.jpg", mask_hat)
# 使用取反操作,将嘴巴的图像从黑色0变为白色255,将白色255变成黑色0
mask_hat_inv = cv2.bitwise_not(mask_hat)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("mask_hat_inv.jpg", mask_hat_inv)
# 使用按位与操作,将抠出的嘴巴区域和取反后的嘴巴图像相加
img1_bg = cv2.bitwise_and(small_img_hat, small_img_hat, mask=mask_hat_inv)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("img1_bg.jpg", img1_bg)
# 使用按位与操作,将像素值在[10,255]之间的帽子RGB区域抠取出来
img2_fg = cv2.bitwise_and(imgComposeSize, imgComposeSize, mask=mask_hat)
dst = cv2.add(img1_bg, img2_fg)
# img_bg = cv2.bitwise_and(roi_face, roi_face, mask=mask_eyeglass_inv)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("dst.jpg", dst)
# 将带了嘴巴的局部区域,贴合到原始图像上
frame[top:top + height_hat_new, x0:x0 + width_hat_new] = dst
out1.write(frame)
img = cv2.resize(frame, (800, 600))
# 显示图片
cv2.imshow("image", img)
# 显示图片停顿的时间,如果是0,则一直显示。如果是100,则显示100ms
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 按‘q’退出
except:pass
### 函数主入口
# if __name__ == '__main__':
# 新建一个解析器
def zuibab5():
parser = argparse.ArgumentParser()
# 为解析器添加选项,比如image_path,添加图片地址,可以更换其他图片尝试。(在default后面,添加需要读取的图片路径)
# 注意:不同的图片,宽高大小可能不同,大家可以根据自己的图片比例,调试前面的的cv2.resize中的数值,修改显示窗口的大小。
parser.add_argument('--video_path', default=0, help='path of cap video')
# apath = os.path.abspath("mao1.png")
# print(apath)
# 为解析器添加选项,比如hat_path,添加嘴巴图片地址。(在default后面,添加需要读取的嘴巴图片路径)
parser.add_argument('--hat_path', default="./image/zui5.1.png", help='path of hat image')
parser.add_argument('--landmarks_model_path', default="shape_predictor_68_face_landmarks.dat", help='path of model')
# 解析选项的参数
opt = parser.parse_args()
# 调用hat_face函数,对人脸进行检测,添加嘴巴特效
hat_face(opt)
#帽子特效:
import cv2 # 图像处理的opencv库
import argparse # 加载解析模块
import os
def hat_face(opt):
# 加载dlib的人脸检测模型
detector = dlib.get_frontal_face_detector()
# 使用opencv中的imread函数,读取需要添加特效的图片
landmark_predictor = dlib.shape_predictor(opt.landmarks_model_path)
# 使用opencv中的imread函数,读取兔子帽子的图片
img_hat = cv2.imread(opt.hat_path)
# img_hat = img_hat[:]
# 对图片进行dlib人脸检测,得到检测后的人脸框信息faceRects
# faceRects = detector(img, 0)
# 图片中可能存在多张人脸,依次遍历输出每张人脸的位置信息,并在特定位置,添加兔子帽子特效
cap = cv2.VideoCapture(opt.video_path)
frame_id = 0
while cap.isOpened():
# 因为视频采集,每秒可能会采集N帧图片,因此使用read函数,逐帧读取图片
# ret 返回True或Fasle,表示是否读取到图片
# frame 返回读取的图片信息
ret, frame = cap.read()
# 如果ok为false,则采集结束
if not ret:
# 打印输出,提示信息
print("Camera cap over!")
continue
# frame_id加1,便于跳帧
frame_id += 1
if not int(frame_id) % 2 == 0: continue
faceRects = detector(frame)
if len(faceRects) > 0:
for box_info in faceRects:
# dlib检测出的人脸位置信息,为rectangle类型,所以可以通过left()、top()、right()、bottom()提取人脸框左上角的x0,y0,右下角的x1,y1。
x0, y0, width_face, height_face = box_info.left(), box_info.top(), box_info.right() - box_info.left(), box_info.bottom() - box_info.top()
landmarks = landmark_predictor(frame, box_info)
# 获得帽子图片的高height_hat,宽width_hat,便于后面控制帽子显示的大小
height_hat, width_hat = img_hat.shape[0], img_hat.shape[1]
# 将帽子的高度变成,适合检测到的脸型的大小
imgComposeSizeH = int(height_hat / width_hat * width_face)
# 因为帽子在脸部上方,当脸部靠近视频顶部,为了保证帽子能显示出来,帽子的高度默认为脸部到视频上方的距离
if imgComposeSizeH > (y0 - 20):
imgComposeSizeH = (y0 - 20)
# 将帽子的图片归一化到适合的宽和高大小,宽度为人脸的宽度,高度为上面调整后的帽子高度
imgComposeSize = cv2.resize(img_hat, (width_face, imgComposeSizeH), interpolation=cv2.INTER_NEAREST)
top = (y0 - 20 - imgComposeSizeH )
# 当人脸太靠近图片上方,通过前一行的计算,有可能为负数,所以当出现这样的情况时,top设置为0
if top <= 0:
top = 0
height_hat_new, width_hat_new = imgComposeSize.shape[0], imgComposeSize.shape[1]
small_img_hat = frame[top:top + height_hat_new, x0:x0 + width_hat_new]
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("small_img_hat.jpg",small_img_hat)
# 将帽子图像,从RGB彩色图像转换为灰度图像
small_img_hat_gray = cv2.cvtColor(imgComposeSize, cv2.COLOR_RGB2GRAY)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
ret, mask_hat = cv2.threshold(small_img_hat_gray, 10, 255, cv2.THRESH_BINARY)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("mask_hat.jpg", mask_hat)
# 使用取反操作,将帽子的图像从黑色0变为白色255,将白色255变成黑色0
mask_hat_inv = cv2.bitwise_not(mask_hat)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("mask_hat_inv.jpg", mask_hat_inv)
# 使用按位与操作,将抠出的帽子区域和取反后的帽子图像相加
img1_bg = cv2.bitwise_and(small_img_hat, small_img_hat, mask=mask_hat_inv)
# 如需查看,上一行的效果,可将cv2.imwrite前面的#取消,运行后,保存到本目录查看
#cv2.imwrite("img1_bg.jpg", img1_bg)
# 使用按位与操作,将像素值在[10,255]之间的帽子RGB区域抠取出来
img2_fg = cv2.bitwise_and(imgComposeSize, imgComposeSize, mask=mask_hat)
# 将img1_bg和img2_fg相加,等于戴了帽子的区域图像
dst = cv2.add(img1_bg, img2_fg)
frame[top:top + height_hat_new, x0:x0 + width_hat_new] = dst
img = cv2.resize(frame, (800, 600))
# 显示图片
cv2.imshow("image", img)
# 显示图片停顿的时间,如果是0,则一直显示。如果是100,则显示100ms
if cv2.waitKey(2) & 0xFF == ord('q'):
break
# 按‘q’退出
### 函数主入口
# if __name__ == '__main__':
# 新建一个解析器
def maoc1():
parser = argparse.ArgumentParser()
# 为解析器添加选项,比如image_path,添加图片地址,可以更换其他图片尝试。(在default后面,添加需要读取的图片路径)
# 注意:不同的图片,宽高大小可能不同,大家可以根据自己的图片比例,调试前面的的cv2.resize中的数值,修改显示窗口的大小。
parser.add_argument('--video_path', default=0, help='path of cap video')
# apath = os.path.abspath("mao1.png")
# print(apath)
# 为解析器添加选项,比如hat_path,添加帽子图片地址。(在default后面,添加需要读取的帽子图片路径)
parser.add_argument('--hat_path', default="./image/m8.png", help='path of hat image')
parser.add_argument('--landmarks_model_path', default="shape_predictor_68_face_landmarks.dat", help='path of model')
# 解析选项的参数
opt = parser.parse_args()
# 调用hat_face函数,对人脸进行检测,添加兔子帽子特效
hat_face(opt)
3. 系统关键技术
本作品是使用python语言进行开发设计,主要使用到pyqt5、opencv、dlib、math、requests、bs4等第三方库来实现。作品在读取图片和视频数据的功能上是使用opencv库来实现,除了对图像数据的读取外,还有一关键功能,就是为识别的人像进行68点关键点描点;dlib库是我们作品实现的关键技术,它是基于opencv对人像的描点进行检测,使人脸关键点定位更加精准,为我们后续的特效添加起到了重要的作用;并且通过dlib来进行调参算法对paddlehub框架进行优化;pyqt5模块支撑着我们作品的“排面”,界面设计简约,极易理解,非常容易上手。顺应时下流行的短视频媒体平台的潮流和广大用户的需要,以飞桨平台的模型调用便捷性,结合python开发技术,将图像视频处理工具进行打包,将一个具备免费、免安装、免网络的全民使用工具呈现给大家。
3.1 图像与视频数据读取的实现
图像与视频的读取是我们工具必备的功能,图像和视频的读取不仅可以选择本地已有素材,在借助python的opencv模块功能下实现了可以实时进行拍摄、录制素材。在获取实时素材这一部分,我们加入了异常判断指令,使得获取的图像可以清晰、无延迟地显示到客户端,从而较好地实现了拍摄的实时效果,为后续对图片和视频进行处理奠定了基础。
这里提供简单的内容展示:
def Jietu(self):
try:
import time
import win32com.client
speak = win32com.client.Dispatch("SAPI.SpVoice")
# speak.Speak("正在获取图片")
self.da = []
times = str(round(time.time()))
cap = cv2.VideoCapture(0)
ret, frame = cap.read() # cao.read()返回两个值,第一个存储一个bool值,表示拍摄成功与否。第二个是当前截取的图片帧。
cv2.imwrite(f"./capture1_{times}.jpg", frame) # 写入图片
cap.release() # 释放
self.da.append(f"./capture1_{times}.jpg")
time.sleep(0.2)
self.labbeltu.setPixmap(QPixmap(self.da[0]))
self.path_files1 = [1]
self.path_files1[0] = self.da[0]
speak.Speak("正在识别图片")
except:
pass
3.2 人脸关键点定位的调参优化
在图像处理中,关键点本质上是一种特征。它是对一个固定区域或者空间物理关系的抽象描述,描述的是一定邻域范围内的组合或上下文关系。它不仅仅是一个点信息,或代表一个位置,更代表着上下文与周围邻域的组合关系。关键点检测的目标就是通过计算机从图像中找出这些点的坐标,作为计算机视觉领域的一个基础任务,关键点的检测对于高级别任务,例如识别和分类具有至关重要的意义。
关键点检测方法总体上可以分成两个类型,一个种是用坐标回归的方式来解决,另一种是将关键点建模成热力图,通过像素分类任务,回归热力图分布得到关键点位置。这两个方法,都是一种手段或者是途径,解决的问题就是要找出这个点在图像当中的位置与关系。其中人脸关键点检测是关键点检测方法的一个成功实践。我们作品也将人脸关键点定位的功能完美应用其中。
这里提供 瘦脸优化 和 美白优化 的代码实例:
def thin_face(image, face_landmark):
"""
实现自动人像瘦脸
image: 人像图片
face_landmark: 人脸关键点
"""
end_point = face_landmark[30]
# 瘦左脸,3号点到5号点的距离作为瘦脸距离
dist_left = np.linalg.norm(face_landmark[3] - face_landmark[5])
image = local_traslation_warp(image, face_landmark[3], end_point, dist_left)
# 瘦右脸,13号点到15号点的距离作为瘦脸距离
dist_right = np.linalg.norm(face_landmark[13] - face_landmark[15])
image = local_traslation_warp(image, face_landmark[13], end_point, dist_right)
return image
def whitening(img, face_landmark):
"""
美白
"""
# 简单估计额头所在区域
# 根据0号、16号点画出额头(以0号、16号点所在线段为直径的半圆)
radius=(np.linalg.norm(face_landmark[0] - face_landmark[16]) / 2).astype('int32')
center_abs=tuple(((face_landmark[0] + face_landmark[16]) / 2).astype('int32'))
angle=np.degrees(np.arctan((lambda l:l[1]/l[0])(face_landmark[16]-face_landmark[0]))).astype('int32')
face = np.zeros_like(img)
cv2.ellipse(face,center_abs,(radius,radius),angle,180,360,(255,255,255),2)
# cv2.ellipse(face, center_abs, (radius, radius), angle, 180, 360, (0,0,0), 2)
points=face_landmark[0:17]
hull = cv2.convexHull(points)
cv2.polylines(face, [hull], True, (255,255,255), 2)
# cv2.polylines(face, [hull], True, (0,0,0), 2)
3.3 界面的设计与制作
本功能是使用Pyqt5模块来进行工具GUI界面设计与制作。Pyqt5是基于图形程序框架Qt5的Python语言实现,由一组Python模块构成,是目前最主流的Python GUI框架。功能资源强大的同时又方便快捷。通过使用pyqt5模块可以很容易的对工具界面进行精美的设计和制作。并且在python打包的qt工具中,pyqt5库支持跨平台使用。
4. 功能介绍
我们的工具主要对图片、视频进行处理,包括人像美颜、视频制作、等功能,具有方便、免安装、免费的优势。分为两大功能,分别是图片处理工具和视频处理工具,并且支持现场拍摄和现场录制视频来进行处理。
4.1 图像处理工具
图片处理工具是本作品中的一种功能工具,它对于图片的风格化处理、图像质量的提升等功能有着很全面的实现,下面是图片处理工具的功能介绍图:
下面是我们的图片处理工具的界面图展示图:
可以通过选取本地图片或者现场拍摄的图片来选择瘦脸处理、眼睛处理、美白以及黑白图片上色等功能。
实时拍摄图片来进行处理,更是我们图像视频工具的一大特点:
操作流程:
Step1 选择需要处理的照片
可以选择本地已有的照片或者现场拍摄的照片
Step2 选择需要处理的功能
使用图片风格美化和图片质量提升等功能
Step3 进行美化处理
使用人像处理、人像美颜、图片上色,抠图等来对图片进行美化
Step4 检查图片
检查处理后的图片是否符合自己的要求
Step5 保存图片
将处理后的图片用原图进行保存
4.2 视频处理工具
视频处理工具在本作品中,主要体现的是特效的添加。对于人脸的定位来进行精准的特效添加。
下面是我们作品的视频处理工具的界面展示图:
可以选择不同的特效来进行实时的录像。
效果展示图:
效果展示图:
操作流程:
Step 1 选择需要做处理的视频
可以直接添加本地视频或者现场实时录制视频
Step 2 选择需要的功能
工具中带有视频风格化处理、AI换脸、视频剪辑等功能
Step 3 进行调试
可以随意播放处理后视频,观看是否满足要求并进行调整
Step 4 保存视频
将处理后的视频保存到与原视频相同的路径下,并且不覆盖原视频
4.3 工具操作流程
由于本作品是一款面向大众的功能性工具,而流程图是流经一个系统的信息流、观点流或部件流的图形代表,可以让用户更加直观的了解和使用我们的工具。下面是本工具的操作流程图:
用户可以根据我们的流程图通过简单的操作来实现图像视频处理。
5. 总结
经过几个月的设计和编码,作品《咔秀》基本开发完毕。基本实现了预定完成的功能。本文阐述了该工具的基础理论、实现过程和关键技术。由于篇幅的原因,不可能把整个系统中的每一项技术,每一个细节具体地讲出来,因此,我们只是有选择地对系统中的一些内容进行了介绍。不足之处,还望各位指教。
通过使用python语言中dilib人像关键点定位、opencv库等各种技巧,通过opencv库对图片和视频进行处理,使用photoshop工具设计图片。并且结合dlib库,利用设备摄像头进行人脸捕捉。从而定位人脸关键点,对人脸所在位置添加特效。
在作品设计期间,学习了python语言编程,用到的主要技术有pyqt5(界面设计)、opencv(读取摄像头)、dlib(人脸关键点定位)、、match(模块算法)、requests(数据获取)、bs4等主要技术,并查看学习了许多资料。在系统的研发过程中,我们也遇到许多困难,因为以前没有项目经验,起步很难,不过通过各种知识的补充学习,并且查找各种资料,团队慢慢进入状态,并且从中找到很多乐趣。
本系统经过测试,效果良好,但是由于时间有限,技术上存在许多需要改进之处。在功能上还有许多待完善的地方,比如可以增加特效种类,对特效进行动态处理在视频中增加互动,这些设想我们都在进一步的研究与实现。希望通过我们今后的不断努力,我们的作品不断扩大应用范围,真正服务于图片、视频特效这个领域。
此文仅为搬运,原作链接:https://aistudio.baidu.com/aistudio/projectdetail/4264449?channelType=0&channel=0
更多推荐
所有评论(0)