ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

使用 OpenCV Contrib face 模块训练自定义人脸关键点检测器(FacemarkKazemi 实战指南)

使用 OpenCV Contrib face 模块训练自定义人脸关键点检测器(FacemarkKazemi 实战指南) 计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载本指南围绕 opencv_contrib 的 face 模块中face_landmark_trainer教程展开系统讲解如何基于 HELEN / ibug 格式的标注数据使用FacemarkKazemi算法训练属于自己的 68 点人脸关键点检测模型。读完本文你将掌握训练数据的组织格式、全部命令行参数与 8 个核心训练超参数的含义及源码级默认值并能独立跑通sample_train_landmark_detector与sample_train_landmark_detector2两个官方训练样例理解整个级联回归训练流程的底层实现。概述训练器能做什么modules/face模块提供的训练应用用于训练自定义的人脸关键点检测器face landmark detector。你只需提供两类输入存放训练图片的目录与图片一一对应的关键点标注文件。算法会自动完成人脸检测、尺度归一、均值形状计算、级联回归器训练最终产出一个可直接用于Facemark::loadModelFacemark::fit推理流程的模型文件。由于该检测器最初是在 HELEN 数据集 上训练的其训练数据格式与 HELEN 数据集保持一致也兼容 ibug 人脸标注点数据集的标准格式见后文。训练数据格式准备HELEN 风格标注.txt单文件格式数据集由若干.txt文件构成每个文件的第一行是图片文件名后续每一行是一个关键点的x,y坐标。格式如下/directory/images/abc.jpg 123.45,345.65 321.67,543.89 .... , .... .... , ....对应到源码这一格式由 facemark_train.hpp 中声明的loadTrainingData(std::vectorString filename, ...)重载解析第一个字段为图片路径后续逐行读取形如x,y的坐标对。ibug 风格标注.pts文件格式若你使用的是 ibug 人脸标注点数据集68 点标准其单个.pts标注文件格式为version: 1 n_points: 68 { 115.167660 220.807529 116.164839 245.721357 120.208690 270.389841 ... }其中n_points声明关键点总数每个点以空格分隔的x y坐标表示。这类格式由loadFacePoints与两文件列表式loadTrainingData重载支持见 facemark_train.hpp并且要求同时提供两个列表文件# images.txt 内容示例 ../trainset/image_0001.png ../trainset/image_0002.png # annotations.txt 内容示例 ../trainset/image_0001.pts ../trainset/image_0002.pts两个列表逐行对应指明每张图片及其标注文件的位置。对应的加载调用为std::vectorString images; std::vectorstd::vectorPoint2f facePoints; loadTrainingData(imagesList, annotations, images, facePoints, 0.0);其中最后一个参数offset默认0.0用于对加载到的点坐标做整体平移修正。命令行参数说明运行官方样例sample_train_landmark_detector的命令源码见 sample_train_landmark_detector.cpp./sample_train_landmark_detector -annotations/home/sukhad/Downloads/code/trainset/ -configconfig.xml -face_cascadelbpcascadefrontalface.xml -modeltrained_model.dat -width460 -height460各参数含义如下表参数简写必填说明annotationsa是存放标注.txt文件的目录路径HELEN 风格例如/data/annotations.txtconfigc是训练配置文件XML路径内含全部训练超参数例如/data/config.xmlmodelm是训练完成后模型保存路径例如/data/model.datwidthw否训练前将所有图片缩放到的目标宽度用于加速处理大图默认460heighth否训练前将所有图片缩放到的目标高度默认460face_cascadef是训练期用于人脸检测的 Haar/LBP 级联分类器 XML 路径例如lbpcascadefrontalface.xml要点说明源码中默认的width、height均为460与文档描述一致官方示例提示尽量使用绝对路径以避免路径解析问题若缺少任一必填参数程序会打印参数帮助信息并返回错误码见 sample_train_landmark_detector.cpp。训练配置文件与 8 个核心超参数训练配置文件是一个标准的 OpenCVFileStorageXML 文件官方示例 sample_config_file.xml 内容如下?xml version1.0? opencv_storage cascade_depth15/cascade_depth tree_depth4/tree_depth num_trees_per_cascade_level500/num_trees_per_cascade_level learning_rate1.0000000149011612e-01/learning_rate oversampling_amount20/oversampling_amount num_test_coordinates400/num_test_coordinates lambda1.0000000149011612e-01/lambda num_test_splits20/num_test_splits /opencv_storage文档中给出的 8 个参数含义如下cascade_depth级联深度训练所用回归器级联cascade of regressors的级数tree_depth树深度梯度提升过程中作为弱学习器的决策树深度num_trees_per_cascade_level每级级联的树数量每一级级联所需训练的树的总数learning_rate学习率梯度提升的学习率用于通过收缩shrinkage防止过拟合oversampling_amount过采样量对训练样本的过采样倍数num_test_coordinates测试坐标数为决定分裂而生成的候选测试坐标数量lambdaλ用于计算像素选择概率的值帮助在分裂时选取更靠近当前形状的像素num_test_splits测试分裂数在选出最优分裂之前生成的候选分裂数量。这些参数的理论出处是论文One Millisecond Face Alignment with an Ensemble of Regression TreesVahid Kazemi Josephine Sullivan即 FacemarkKazemi 算法所依据的研究论文。源码级默认值与解析逻辑参数默认值定义在 face_alignment.cpp 的FacemarkKazemi::Params::Params()中参数源码默认值示例配置文件值cascade_depth1515tree_depth54num_trees_per_cascade_level500500learning_rate0.10.1oversampling_amount2020num_test_coordinates500400lambda0.10.1num_test_splits2020配置文件的实际读取在 trainFacemark.cpp 的setTrainingParameters中完成通过FileStorage以READ模式打开 XML逐个键读取上述 8 个字段并写入params结构若配置文件无法打开会抛出Error while opening configuration file.Aborting..异常。因此训练前必须保证该文件存在且字段键名与上表完全一致。训练代码逐段解析文档在 Understanding code 章节给出完整的训练主流程下面结合源码与官方样例逐段说明。第一步自定义人脸检测器训练过程需要先找到每张图片中的人脸区域。FacemarkTrain基类允许用户注入自己的人脸检测函数facemark_train.hpp 中的setFaceDetector检测器函数签名类型为FN_FaceDetectortypedef bool(*FN_FaceDetector)(InputArray, OutputArray, void* userData);文档中的示例检测器基于 Haar 级联CascadeClassifier face_cascade; bool myDetector( InputArray image, OutputArray ROIs ); bool myDetector( InputArray image, OutputArray ROIs ){ Mat gray; std::vectorRect faces; if(image.channels()1){ cvtColor(image.getMat(),gray,COLOR_BGR2GRAY); } else{ gray image.getMat().clone(); } equalizeHist( gray, gray ); face_cascade.detectMultiScale( gray, faces, 1.1, 3,0, Size(30, 30) ); Mat(faces).copyTo(ROIs); return true; }该函数将彩色图转灰度、做直方图均衡化后调用detectMultiScale把检出的人脸矩形框写入ROIs。官方样例实现略有差异级联参数为scaleFactor1.4、minNeighbors2、CASCADE_SCALE_IMAGE标志与Size(30,30)最小尺寸见 sample_train_landmark_detector.cpp并且通过void* userData把CascadeClassifier指针传入检测函数。第二步扫描标注文件vectorString filenames; glob(directory,filenames);glob遍历指定目录把其中所有标注.txt文件名存入filenames向量供后续加载使用官方样例实际调用glob(directory *.txt, filenames)。第三步创建 Facemark 实例并注入检测器Mat img imread(image); face_cascade.load(cascade_name); FacemarkKazemi::Params params; params.configfile configfile_name; PtrFacemark facemark FacemarkKazemi::create(params); facemark-setFaceDetector(myDetector);流程要点face_cascade.load(cascade_name)加载命令行指定的级联模型FacemarkKazemi::Params中的configfile字段指向训练配置文件官方样例与源码training()均会据此调用setTrainingParametersFacemarkKazemi::create(params)创建算法实例工厂实现见 face_alignment.cppsetFaceDetector将第一步定义的检测器注入 facemark训练期间用它定位人脸。注意FacemarkTrain::setFaceDetector的完整签名还接收userData指针setFaceDetector(FN_FaceDetector detector, void* userData 0)。第四步加载图片与标注HELEN 风格数据加载vectorString imagenames; vector vectorPoint2f trainlandmarks,Trainlandmarks; vectorMat trainimages; loadTrainingData(filenames,trainlandmarks,imagenames); for(unsigned long i0;i300;i){ string imgname imagenames[i].substr(0, imagenames[i].size()-1); string img directory string(imgname) .jpg; Mat src imread(img); if(src.empty()){ cerrstring(Image img not found\n.)endl; continue; } trainimages.push_back(src); Trainlandmarks.push_back(trainlandmarks[i]); }loadTrainingData解析每个.txt标注文件把图片名与逐点坐标分别填入imagenames与trainlandmarks随后循环读取对应图片跳过加载失败的文件。注意substr(0, size()-1)是为了去掉文件名末尾的换行符。ibug 风格.pts数据加载则直接使用两列表重载std::vectorString images; std::vectorstd::vectorPoint2f facePoints; loadTrainingData(imagesList, annotations, images, facePoints, 0.0);此重载读取图片列表与标注列表两个文件得到图片路径与对应的 68 点标注。对应完整样例见 sample_train_landmark_detector2.cpp。第五步执行训练facemark-training(Trainimages,Trainlandmarks,configfile_name,scale,modelfile_name);training的重载签名实现于 trainFacemark.cppimages训练图片landmarks与图片一一对应的标注点filename训练配置 XML 路径scale所有图片与标注的目标缩放尺寸由width/height命令行参数决定modelFilename训练完成后的模型保存路径。训练开始成功后控制台会输出类似下面的训练进度对应文档配图 train1.png训练流程的源码级原理结合 trainFacemark.cpp 与 regtree.cppFacemarkKazemiImpl::training的内部执行顺序为setTrainingParameters(filename)读取并校验配置文件中的 8 个超参数scaleData(landmarks, images, scale)按scale目标尺寸等比缩放所有图片与标注点scalex scale.width / img.colsscaley scale.height / img.rows缩放后用INTER_LINEAR_EXACT重采样这是文档强调大图处理慢的工程化解法calcMeanShape(landmarks, images, rectangles)对每张图用人脸检测器求人脸框通过仿射变换convertToUnit将各形状统一到单位参考系逐点累加平均得到均值形状mean shape作为训练与推理的初始形状getTestCoordinates()在每个级联层级内、以均值形状的包围范围为界随机生成num_test_coordinates个候选像素坐标createTrainingSamples按oversampling_amount倍扩充训练样本——半数样本以均值形状为当前形状半数以随机其他样本的真实形状为当前形状并通过getDiffShape并行计算残差actual_shape - current_shape逐级联训练森林对每一级cascade_depth级调用gradientBoosting每级训练num_trees_per_cascade_level棵回归树。gradientBoosting中通过parallel_for_的splitSamples并行执行分裂搜索regtree.cpp随机取两测试坐标feat.index1/index2范围受num_test_coordinates约束生成num_test_splits个候选分裂并择优树节点数以2^tree_depth计算叶节点按learning_rate收缩更新残差regtree.cppsaveModel(modelFilename)以二进制流写出模型内容包括cascade_depth、各级pixel_coordinates、mean_shape、num_trees以及逐棵树的 split/leaf 节点见 trainFacemark.cpp。从源码结构可以推断training()的每一步缩放、均值形状、样本过采样、级联森林、模型序列化都直接受配置文件中对应超参数驱动这也是为什么config文件是必填参数。训练效果评估与误差曲线训练完成后模型的精度与训练样本数量正相关。文档给出的两组典型关系曲线如下训练集上的误差率随训练图片数量的变化测试集上的误差率随训练图片数量的变化从曲线趋势可以直观看出样本越少时误差越高且波动明显随着训练图片数量增加训练集与测试集误差均收敛到较低水平这也解释了为何官方样例默认取前 300 张图片训练——需要在数据规模与训练耗时之间取得平衡。训练完成后如何复用模型训练产物如trained_model.dat可在其他应用中直接加载推理典型流程来自 facemark.hpp 中定义的通用 Facemark 管线PtrFacemark facemark FacemarkKazemi::create(); facemark-loadModel(trained_model.dat); // 加载训练好的模型 std::vectorRect faces; std::vectorstd::vectorPoint2f landmarks; facemark-fit(image, faces, landmarks); // 拟合关键点其中faces可以由训练期使用的同一人脸检测器提供。检测与视频流应用可进一步参考同目录下的 face_landmark_detection.markdown 与 face_landmark_video.markdown 教程。小结本指南完整覆盖了FacemarkKazemi自定义训练的全部要素HELEN 与 ibug 两种标注格式、6 个命令行参数、8 个训练超参数及其源码默认值、自定义人脸检测器的注入方式以及从数据加载、缩放、均值形状到级联回归森林的底层训练流程。按此流程准备好标注数据与配置文件后即可用官方两个样例sample_train_landmark_detector.cpp、sample_train_landmark_detector2.cpp训练出适配自有数据分布的人脸关键点模型再通过loadModelfit投入实际应用。赞分享计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载相关推荐使用 OpenCV 人脸模块训练自定义人脸关键点检测器FacemarkKazemi使用 OpenCV 人脸模块训练自定义人脸关键点检测器FacemarkKazemi 本教程基于 OpenCV 扩展模块 opencv_contrib 的 f计算机视觉图像处理深度学习机器学习OpenCV contrib 人脸关键点检测实战基于 FacemarkKazemi 的图像 Landmark 检测指南OpenCV contrib 人脸关键点检测实战基于 FacemarkKazemi 的图像 Landmark 检测指南 人脸关键点Facial Landma计算机视觉图像处理机器学习OpenCV 人脸识别与人脸关键点检测实战指南基于 opencv_contrib face 模块从训练到部署OpenCV 人脸识别与人脸关键点检测实战指南基于 opencv_contrib face 模块从训练到部署 本篇技术指南以 opencv_contrib 的计算机视觉图像处理机器学习上一篇如何解决SpERT实体识别误报问题neg_entity_count参数调优指南下一篇FSLineChartiOS平台的优雅折线图库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表