发布时间:2023-03-08 13:30
首先,看上图可以清楚mtcnn会对传入图片做四大步处理。第一大步为Resize,在这步中只是数据预处理的过程,还没有传入神经网络中。它会将原图片resize成越来越小的尺寸,最小边长为12,这里我们只要知道这步是在干什么就行了,为什么最小边长为12,接下来会讲。
第二大步,也就是Stage 1 P-Net,这次就是把第一步resize的各种尺寸图片传过来,这个时候就传入了P-Net的卷积神经网络。神经网络输出两个参数,一个是白框的置信度另一个就是回归系数信息。 整体的网络是这样婶的:
conv4-2输出的是回归系数,prob1则输出的为box框的置信信息和置信度(是人脸的概率)。也就是说每次reshape之后的图片都会传入这个网络中,conv4-2和prob1都会输出。再来解释下为什么最小边长为12,如果边长12输入网络则到conv2层时维度为3x3x16,紧接着又有一个3x3的卷积核16通道到conv3这是最小的边长才能在这一层来卷积,再小边长这个网络就跑不通了。 这就是原因。
接下来做的事情,就是根据P-Net的输出来生成box,prob1输出的置信度在这里就起了作用,我们可以设定阈值(通常为0.6),得到候选框,在候选框中心设立一个点,然后以此点为左上角,向右向下各扩展12像素,得到12x12的矩形框。然后对一帧图像上检测到的所有的12x12矩形框进行nms运算(nms作用就是合并12x12的矩形框),最后得到的所有box(几百个吧)会放置在一个四维数组里,这个数组是 numbox9 维度的,numbox就是box的数量,9分别代表x1, y1, x2, y2, score, reg_x1, reg_y1, reg_x2, reg_y2; 这里面的reg系列是针对对应的坐标值的线性回归系数。通过这种回归可以将PNet给出的box进行修正,可以使用下面的代码来表达这个过程:
new_x1 = x1 + reg_x1 * width_of_box
new_y1 = y1 + reg_y1 * height_of_box
new_x2 = x2 + reg_x2 * width_of_box
new_y2 = y2 + reg_y2 * height_of_box
width(height)_of_box代表的就是合并的box的宽度和高度。
接下来做的事情就是要将矩形框变成正方形,因为下一层网络(R-Net)输入的要求,这种操作叫rec2square。想象一下,一张图片,你画出的人脸框是个瘦长型的,将其变成方形是不是宽度变大,有没有可能会突破本来图片的宽度,答案是有可能的。这个时候就需要类似于卷积的时候的padding操作。所以总结下来就是在对box框修正之后会进行rec2square然后再进行padding。 最后再将这些box框resize到24x24x3,准备送往下一次R-Net网络。至此,P-Net层结束。
第三大步,开始往R-Net网络输入这些被P-Net筛选过的box框的图像,最终网络也是有两个输出,一个是prob1的置信度信息,conv5-2的回归系数信息。和P-Net输出一样,只是网络结构稍有不同。下面贴出R-Net的网络结构:
接下来做的事情和P-Net一样,输出的两个信息会通过阈值(通常0.7)过滤掉一些原来的box,剩余的box经过nms操作,然后再进行回归、rec2square、pad操作。最后再将这些box框resize到48x48x3,准备送往下一层O-Net网络。至此,R-Net层结束。
第四大步,将这些剩下的box输入到O-Net网络,O-Net网络会有三个输出,prob1层的置信度信息、conv6-3层的关键点信息、conv6-2层的回归系数信息。多了一个关键点信息,也就是mtcnn最后实现的人脸关键点的检测。下面将O-Net网络结构贴出来:
接下来做的事情我们会根据prob1输出,将置信度小于0.7的box扔掉。然后根据conv6-2层的线性回归信息再次修正目标框,然后以0.7的阈值最后做一次nms。对于con6-3层的关键点信息,这是一个numbox*10的二维数组,numbox代表目标框的数量,对于每一个框来说有10个元素,前5个是x坐标信息,后5个是y坐标信息,格式是[Rx1,Rx2, Rx3, Rx4, Rx5, Ry1, Ry2, Ry3, Ry4, Ry5];这里面的R是关键点在目标框内部的距离的比例,假设目标框的左上角坐标为Ox, Oy,宽为w, 高为h,那么第一个关键点在原图上的坐标点是 x = Rx1 * w + Ox - 1;y = Ry1 * h + Oy - 1。
至此,mtcnn的人脸检测流程就走完了,通过O-Net的输出,我们就可以在借助opencv等工具画出人脸框和人脸关键点信息了。