资讯动态

基于 YOLO V8 Pose Fine-Tuning 训练 15 点人脸关键点检测模型

发布时间:2026/10/27 1:14:00 来源:尧图企业网站定制
一、YOLO V8 PoseYOLO V8在上篇文章中进了简单的介绍并基于YOLO V8 Fine-Tuning训练了自定义的目标检测模型而YOLO V8 Pose是建立在YOLO V8基础上的关键点检测模型本文基于yolov8n-pose模型实验Fine-Tuning训练15点人脸关键点检测模型并配合上篇文章训练的人脸检测模型一起使用。上篇文章地址基于 YOLO V8 Fine-Tuning 训练自定义的目标检测模型YOLO V8的细节可以参考下面官方的介绍https://docs.ultralytics.com/zh/models/yolov8/#citations-and-acknowledgements本文依旧使用ultralytics框架进行训练和测试其中ultralytics和pytorch的版本如下torch1.13.1cu116ultralytics8.1.37YOLO V8 Pose调用示例如下测试图像这里使用yolov8n-pose模型如果模型不存在会自动下载fromultralyticsimportYOLO# Load a modelmodelYOLO(yolov8n-pose.pt)# pretrained YOLOv8n modelresultsmodel.predict(./img/1.png)# Show resultsresults[0].show()二、人脸关键点检测数据集在计算机视觉人脸计算领域人脸关键点检测是一个十分重要的区域可以实现例如一些人脸矫正、表情分析、姿态分析、人脸识别、人脸美颜等方向。人脸关键点数据集通常有5点、15点、68点、96点、98点、106点、186点等例如通用Dlib中的 68 点检测它将人脸关键点分为脸部关键点和轮廓关键点脸部关键点包含眉毛、眼睛、鼻子、嘴巴共计51个关键点轮廓关键点包含17个关键点。本文基于kaggle的Facial Keypoints Detection中的数据集进行实践该数据集包含包括7,049幅训练图像图像是96 x 96像素的灰度图像其中关键点有15个点注意数据集有的字段缺失如果去除字段缺失的数据实际训练数据只有2,140幅训练图像还包括1,783张测试图片数据集的效果如下所示可以看出关键点包括眉毛的两端、眼睛的中心和两端、鼻子尖、嘴巴两端和上下嘴唇的中间。下载数据集数据集在kaggle的官方网址上https://www.kaggle.com/c/facial-keypoints-detection下载前需要进行登录如果没有kaggle账号可以注册一个。下载解压后可以看到training.zip和test.zip两个文件分别对应训练集和测试集解压后数据是以CSV的格式进行存放的其中training.csv中的字段分别表示序号字段含义0left_eye_center_x左眼中心 x 点1left_eye_center_y左眼中心 y 点2right_eye_center_x右眼中心 x 点3right_eye_center_y右眼中心 y 点4left_eye_inner_corner_x左眼内端 x 点5left_eye_inner_corner_y左眼内端 y 点6left_eye_outer_corner_x左眼外端 x 点7left_eye_outer_corner_y左眼外端 y 点8right_eye_inner_corner_x右眼内端 x 点9right_eye_inner_corner_y右眼内端 y 点10right_eye_outer_corner_x右眼外端 x 点11right_eye_outer_corner_y右眼外端 y 点12left_eyebrow_inner_end_x左眉毛内端 x 点13left_eyebrow_inner_end_y左眉毛内端 y 点14left_eyebrow_outer_end_x左眉毛外端 x 点15left_eyebrow_outer_end_y左眉毛外端 y 点16right_eyebrow_inner_end_x右眉毛内端 x 点17right_eyebrow_inner_end_y右眉毛内端 y 点18right_eyebrow_outer_end_x右眉毛外端 x 点19right_eyebrow_outer_end_y右眉毛外端 y 点20nose_tip_x鼻尖中心 x 点21nose_tip_y鼻尖中心 y 点22mouth_left_corner_x嘴巴左端 x 点23mouth_left_corner_y嘴巴左端 y 点24mouth_right_corner_x嘴巴右端 x 点25mouth_right_corner_y嘴巴右端 y 点26mouth_center_top_lip_x上嘴唇中心 x 点27mouth_center_top_lip_y上嘴唇中心 y 点28mouth_center_bottom_lip_x下嘴唇中心 x 点29mouth_center_bottom_lip_y下嘴唇中心 y 点30Image图形像素由于数据是存放在CSV中可以借助pandas工具对数据进行解析如果没有安装pandas工具可以通过下面指令安装pip3installpandas-ihttps://pypi.tuna.tsinghua.edu.cn/simple下面程序通过pandas解析CSV文件并将图片转为numpy数组通过matplotlib可视化工具查看其中具体的解释都写在了注释中importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltdefmain():csv_path./data/training.csv# 读取 CSV 文件train_dfpd.read_csv(csv_path)# 查看数据框并列出数据集的头部。train_df.info()# 丢弃有缺失数据的样本train_dftrain_df.dropna()# 获取图片信息并转为 numpy 结构x_traintrain_df[Image].apply(lambdaimg:np.fromstring(img,sep ))x_trainnp.vstack(x_train)# 重新修改形状x_trainx_train.reshape((-1,96,96,1))# 去除最后一列的 Imagecolstrain_df.columns[:-1]y_traintrain_df[cols].valuesprint(训练集 shape ,x_train.shape)print(训练集label shape ,y_train.shape)plt.figure(figsize(10,10))forpinrange(2):datax_train[(p*9):(p*99)]labely_train[(p*9):(p*99)]plt.clf()foriinrange(9):plt.subplot(3,3,i1)imgdata[i].reshape(96,96,1)plt.imshow(img,cmapgray)# 画关键点llabel[i]# 从 1 开始每次走 2 步j-1j 就是当前点的坐标forjinrange(1,31,2):plt.plot(l[j-1],l[j],ro,markersize4)plt.show()if__name____main__:main()运行之后可以看到如下效果图下面我们基于该数据集进行建模训练一个自己的关键点检测模型。三、数据集拆分和转换数据集格式需要转换成Ultralytics官方的YOLO格式主要包括以下几点的注意每幅图像一个文本文件数据集中的每幅图像都有一个相应的文本文件文件名与图像文件相同扩展名为.txt。每个对象一行文本文件中的每一行对应图像中的一个对象实例。每行对象信息每行包含对象实例的以下信息对象类别索引代表对象类别的整数如0代表人1代表汽车等。对象中心坐标对象中心的x和y坐标归一化后介于0和1之间。对象宽度和高度对象的宽度和高度标准化后介于0和1之间。对象关键点坐标对象的关键点归一化为0至1。姿势估计任务的标签格式示例class-indexxywidthheightpx1py1px2py2...pxnpyn官方的介绍https://docs.ultralytics.com/zh/datasets/pose/#ultralytics-yolo-format这里由于数据集中仅包含人脸信息没有其他因素影响因此class-index x y width height我们可以固定写死为0 0.5 0.5 1 1转换和拆分的逻辑如下importosimportshutilfromtqdmimporttqdmimportnumpyasnpimportpandasaspdfromPILimportImage# training.csv 地址csv_path./data/training.csv# 训练集的比例training_ratio0.8# 拆分后数据的位置train_dirtrain_datadeftoRgbImg(img):imgnp.fromstring(img,sep ).astype(np.uint8).reshape(96,96)imgImage.fromarray(img).convert(RGB)returnimgdefsplit_data():# 训练集目录os.makedirs(os.path.join(train_dir,images/train),exist_okTrue)os.makedirs(os.path.join(train_dir,labels/train),exist_okTrue)# 验证集目录os.makedirs(os.path.join(train_dir,images/val),exist_okTrue)os.makedirs(os.path.join(train_dir,labels/val),exist_okTrue)# 读取数据train_dfpd.read_csv(csv_path)# 丢弃有缺失数据的样本train_dftrain_df.dropna()# 获取图片信息并转为 numpy 结构x_traintrain_df[Image].apply(toRgbImg)# 去除最后一列的 Image, 将y值缩放到[0,1]区间colstrain_df.columns[:-1]y_traintrain_df[cols].values# 使用 80% 的数据训练20% 的数据进行验证sizeint(x_train.shape[0]*0.8)x_valx_train[size:]y_valy_train[size:]x_trainx_train[:size]y_trainy_train[:size]trains[]vals[]# 生成训练数据fori,imageintqdm(enumerate(x_train),totallen(x_train)):labely_train[i]image_fileos.path.join(train_dir,fimages/train/{i}.jpg)label_fileos.path.join(train_dir,flabels/train/{i}.txt)image.save(image_file)trains.append(image_file)width,heightimage.size yolo_label[0,0.5,0.5,1,1]fori,vinenumerate(label):ifi%20:yolo_label.append(str(v/float(width)))else:yolo_label.append(str(v/float(height)))withopen(label_file,w,encodingutf-8)asw:w.write( .join(yolo_label))# 生成验证数据fori,imageintqdm(enumerate(x_val),totallen(x_val)):labely_val[i]image_fileos.path.join(train_dir,fimages/val/{i}.jpg)label_fileos.path.join(train_dir,flabels/val/{i}.txt)image.save(image_file)vals.append(image_file)width,heightimage.size yolo_label[0,0.5,0.5,1,1]fori,vinenumerate(label):ifi%20:yolo_label.append(str(v/float(width)))else:yolo_label.append(str(v/float(height)))withopen(label_file,w,encodingutf-8)asw:w.write( .join(yolo_label))withopen(os.path.join(train_dir,train.txt),w)asfile:file.write(\n.join([image_fileforimage_fileintrains]))print(save train.txt success!)withopen(os.path.join(train_dir,val.txt),w)asfile:file.write(\n.join([image_fileforimage_fileinvals]))print(save val.txt success!)if__name____main__:split_data()运行后可以在train_data下面看到拆分后的数据四、训练使用ultralytics框架训练非常简单仅需三行代码即可完成训练不过在训练前需要编写YAML配置信息主要标记数据集的位置。创建face.yaml文件写入下面内容# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]path:D:/pyProject/yolov8/face/train_data# dataset root dirtrain:images/train# train images (relative to path) 4 imagesval:images/val# val images (relative to path) 4 imagestest:# test images (optional)# Keypointskpt_shape:[15,2]# number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)# Classes dictionarynames:0:person开始训练fromultralyticsimportYOLO# 加载模型modelYOLO(yolov8n-pose.pt)# 训练model.train(dataface.yaml,# 训练配置文件epochs50,# 训练的周期imgsz640,# 图像的大小device[0],# 设备如果是 cpu 则是 devicecpuworkers0,lr00.001,# 学习率batch8,# 批次大小ampFalse# 是否启用混合精度训练)运行后可以看到打印的网络结构训练中训练结束后可以在runs目录下面看到训练的结果看下训练时loss的变化图三、模型预测首先使用测试集进行测试importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromPILimportImagefromultralyticsimportYOLOdeftoRgbImg(img):imgnp.fromstring(img,sep ).astype(np.uint8)imgImage.fromarray(img).convert(RGB)returnimgdefmain():csv_pathdata/test.csv# 读取 CSV 文件test_dfpd.read_csv(csv_path)# 查看数据框并列出数据集的头部。test_df.info()# 获取图片信息并转为 numpy 结构test_dftest_df[Image].apply(toRgbImg)test_dfnp.vstack(test_df)# 重新修改形状test_dftest_df.reshape((-1,96,96,3))# 加载模型modelYOLO(runs/pose/train/weights/best.pt)plt.figure(figsize(10,10))forpinrange(5):datatest_df[(p*9):(p*99)]plt.clf()foriinrange(9):plt.subplot(3,3,i1)imgdata[i]plt.imshow(img,cmapgray)resultsmodel.predict(img,devicecpu)# 画关键点keypointsresults[0].keypoints.xyforkeypointinkeypoints:forxyinkeypoint:plt.plot(xy[0],xy[1],ro,markersize4)plt.show()if__name____main__:main()可以看到对于鼻子位置的关键点有些会出现偏差。四、结合上篇的人脸检测模型fromultralyticsimportYOLOfromPILimportImagefrommatplotlibimportpyplotaspltdefmain():# 加载人脸检测模型detection_modelYOLO(yolov8_face_detection.pt)# 加载人脸关键点检测模型point_modelYOLO(runs/pose/train/weights/best.pt)imageplt.imread(./img/10.jpg)# 预测resultsdetection_model.predict(image,devicecpu)boxesresults[0].boxes.xyxyprint(boxes)axplt.gca()forboxeinboxes:x1,y1,x2,y2boxe[0],boxe[1],boxe[2],boxe[3]ax.add_patch(plt.Rectangle((x1,y1),(x2-x1),(y2-y1),fillFalse,colorred))# 截取图片cropimage[int(y1):int(y2),int(x1):int(x2)]resultspoint_model.predict(crop,devicecpu)keypointsresults[0].keypoints.xyforkeypointinkeypoints:forxyinkeypoint:plt.plot(xy[0]x1,xy[1]y1,ro,markersize2)plt.imshow(image)plt.show()if__name____main__:main()测试效果

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑