许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  人脸检测与矫正:MTCNN完整流程(包含数据准备、模型训练、模型测试、模型部署)

人脸检测与矫正:MTCNN完整流程(包含数据准备、模型训练、模型测试、模型部署)

阅读数 6
点赞 0
article_banner

Part1 数据

数据集通过网址 http://shuoyang1213.me/WIDERFACE/ 下载  

模型Pnet,Rnet 训练、测试选择使用的数据 WIDER FACE 。

WIDER FACE简介:数据标签只有bbox,没有landmark。注释:bbox [x1,y1,width,height]

模型Onet训练采用的数据通过网址http://mmlab.ie.cuhk.edu.hk/archive/CNN_FacePoint.htm 下载

CNN_FacePoint简介 :数据标签有bbox,以及landmark。注释:bbox[x1,x2,y1,y2]

landmark [x1,y1,x2,y2,x3,y3,x4,y4,x5,y5]

坑1:注意标签每个坐标含义。

Part2 模型训练

工程需要做一个人脸识别的东东,所以准备把人脸识别的每块内容都认真的走一遍,步骤大概是:人脸检测 - 人脸矫正 - 活体检测 - 质量评估 - 人脸识别  ,为了快速搞定,利用别人的代码就是最便捷的方法,自己选择pytorch的一个版本。网址为:https://github.com/Sierkinhane/mtcnn-pytorch

这里大概介绍一下mtcnn的工作原理

mtcnn网络结构如图1所示:

图1

他是一种多任务级联的网络,每一个网络都包含人脸分类任务,边界框回归任务、人脸关键点回归任务。P-Net 主要用来产生候选框可能的位置,R-Net 再过滤掉一部分候选框,O-Net 产生最终的候选框和landmark位置。

注意:PNet 输出的是map格式,而Rnet和ONet的输出的是条状的,原因是因为实际测试时,PNet输入图片大小是不固定的,所以维度是不固定的不能接入全连接层。

测试时,一张图片先通过PNet,按照一个比例系数进行resize 得到图片金字塔,分别在每张图片上面进行边界框预测输出,预测的方法是根据class_map上大于阈值的保留下来,作为边界框的左上角坐标,坐标通过resize 相应的系数映射回原图,右下角的坐标=(坐上角的坐标*stirde+12)/scale。对应红色的部分。stride =2 猜测比如输入一张256大小的图片,最后输出类别、位置信息时图像大小变为123 ,原图是特征图的二倍关系。

boundingbox = np.vstack([np.round((stride * t_index[1]) / scale),            # x1 of prediction box in original image
                         np.round((stride * t_index[0]) / scale),            # y1 of prediction box in original image
                         np.round((stride * t_index[1] + cellsize) / scale), # x2 of prediction box in original image
                         np.round((stride * t_index[0] + cellsize) / scale), # y2 of prediction box in original image #reconstruct the box in original image
                         score,
                         reg])

reg 是网络输出框的相对偏移的位置信息,最终的坐标输出以x1为例,为x1 = np.round((stride * t_index[1]) / scale)+ (np.round((stride * t_index[1] + cellsize) / scale)-np.round((stride * t_index[1]) / scale))*reg[:,0]

RNet输入是Pnet的输出,RNet主要会相对于Pnet输出位置进行调整。ONet同Rnet。landmark 输出的是相对位置,是相对boundingbox的相对位置坐标。

回到模型训练上,PNet,RNet,ONet模型的输入分别是12*12,24*24,48*48。输出的类别共包含0-负样本,1-正样本,-1-part样本就是部分含有正样本的数据,-2-landmark 样本。

需要注意的是模型训练的数据种类标签是否正确,否则训练的时候会出现某一个 loss  的梯度爆炸,原文作者代码的iou 计算输入有些问题,导致在训练ONet正负样本不均衡。

目前训练的PNet,RNet,ONet,比例大致是4:7:15 。

目前模型训练结果出现的问题:

1、框回归的不稳,抖动情况非常严重。这个问题目前没有解决。不知道该怎样优化。可能数据量还是不够。

2、关于参数 初始化  的问题,发现参数初始化不对loss降不太下去,现在每次训练都是在自己某一次实验结果上开始训练的。

Part3 模型测试

自己写了个测试程序,分别统计检出率和准确率。目前iou=0.65,检出和准确率在0.7以上。可以通过这个小程序进行模型筛选。代码如下:

import cv2import torchfrom mtcnn.core.detect import create_mtcnn_net, MtcnnDetectorimport numpy as npimport osimport mtcnn.core.utils as utils testfiles = "anno_train.txt"testdata = "face_landmark/CNN_FacePoint"label = [] showlabel = True with open(testfiles, "r") as f:    read = f.readlines()print("test Data num is :", len(read))pnet, rnet, onet = create_mtcnn_net(p_model_path="pnet_epoch.pt",                                    r_model_path="rnet_epoch.pt",                                    o_model_path="onet_epoch.pt",                                    use_cuda = False)mtcnn_detector = MtcnnDetector(pnet=pnet, rnet=rnet, onet=onet, min_face_size=12) pos = 0numsdetect = 0for file in read:    #print("file is :", file)    file = file.strip().split(" ")    img = cv2.imread(os.path.join(testdata, file[0].replace("\\", "/")))    print(os.path.join(testdata, file[0].replace("\\", "/")))    print("img.shape is :", img.shape)    #print(file[0])    boxes_align_r, bboxs, landmarks = mtcnn_detector.detect_face(img)    gtbox = list(map(float, file[1:5]))    print("gtbox is :", gtbox)    gtlandmarks = list(map(float, file[5:]))    numdetect = len(bboxs)    numsdetect = numsdetect + numdetect    gtbox = np.array(gtbox, dtype=np.float32).reshape(-1, 4)    for box in bboxs:        if showlabel:            cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), (0, 0, 255), 2, 1)            #cv2.rectangle(img, (int(gtbox[0][0]), int(gtbox[0][2])), (int(gtbox[0][1]), int(gtbox[0][3])), (255, 0, 0), 2, 1)            p1 = int(gtbox[0][0])+int(gtbox[0][2])            p2 = int(gtbox[0][1])+int(gtbox[0][3])            print("p1", int(gtbox[0][0]), int(gtbox[0][1]),p1,p2)            cv2.rectangle(img, (int(gtbox[0][0]), int(gtbox[0][1])), (p1, p2), (255, 0, 0),                          2, 1)        iou = utils.IoU1(box, gtbox)        print("iou is :", iou)        if iou > 0.65:             pos = pos + 1    if showlabel:        cv2.imshow("img", img)        cv2.waitKey(1000)print("recall is : %s accuracy is : %s "%(pos/len(read),pos/numsdetect))


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删


相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空