携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
沉淀、分享、成长,让自己和他人都能有所收获!😄
P-Net 详解
其中,P-Net 为一个全卷积神经网络,并且对输入图像的尺寸大小要求为 12x12x3,其中 12x12 代表像素值大小,3 代表 RGB 三通道彩色图像。
因此,在将图像输入 P-Net 网络操作之前,还需对输入的图像进行预处理操作。通常采取的方式为对输入的图像进行多尺度图像金字塔处理,再采取 12x12 大小的滑动窗口对不同尺寸的图像上进行随机的滑动采样后送入 P-Net 网络参与训练。而本章采取的多模板多尺度的图像金字塔的图像预处理方式即对先图像进行多尺度的图像金字塔,而后采取 8x8、12x12、16x16 三种规格的滑窗对在多个尺度的图像上进行滑动采样,从而获得 8x8、12x12、16x16 三种规格的图像块,最后将 8x8 与 16x16 两种规格的图像块在放缩成 12x12 规格的大小后,送入 MTCNN 的 P-Net 网络中进行训练。
该做法保证了送入 MTCNN 网络中的输入图像可以更加适应不同尺寸大小的检测目标,且由于增加了不同规格的滑窗,因此也获取到了更多的不同图像块对数据集起到了一定程度的扩充,对检测的结果也可以起到一定程度的提升作用。因为 P-Net 主要用来进行特征提取并产生区域建议,不需要对原图像进行语义分割等操作,因此不需要反卷积等结构。P-Net 最终可以得到三个特征图作为网络最终的检测结果,分别表示人脸与非人脸的二分类结果、人脸回归框的坐标以及面部五个关键点的坐标。
void MTCNN::detect(ncnn::Mat &img_, std::vector<Bbox> &finalBbox_) {
img = img_;
img_w = img.w;
img_h = img.h;
//各个通道均值
const float mean_vals[3] = {127.5, 127.5, 127.5};
const float norm_vals[3] = {0.0078125, 0.0078125, 0.0078125};
//图像减去均值归一化
img.substract_mean_normalize(mean_vals, norm_vals);
PNet();
if (firstBbox_.size() < 1) return;
nms(firstBbox_, nms_threshold[0]);
refine(firstBbox_, img_h, img_w, true);
RNet();
if (secondBbox_.size() < 1) return;
nms(secondBbox_, nms_threshold[1]);
refine(secondBbox_, img_h, img_w, true);
ONet();
if (thirdBbox_.size() < 1) return;
refine(thirdBbox_, img_h, img_w, false);
nms(thirdBbox_, nms_threshold[2], "Min");
LNet();
finalBbox_ = thirdBbox_;
}
R-Net 详解
R-Net 对输入图像的尺寸大小要求为 24x24x3,即要求图像为 24x24 的像素值大小,同样是 3 通道的彩色图像。该网络不再是全卷积神经网络,而是包含全连接层的普通的卷积神经网络,R-Net 同样可以得到三个输出结果,表示含义与 P-Net 类似。不同于 P-Net 的是,R-Net 采用全卷积结构得到的三个结果表示形式为特征图,而 R-Net 加入了全连接层得到的结果为向量。虽然两个网络检测的目的相同,但是由于网络结构不同,因此得到的结果在数据表达方式上有所不同。
O-Net 详解
O-Net 为网络的第三个部分也是最后一个子网络,该网络的基本结构与 R-Net 相同为一般的卷积神经网络,但是层数要深于 R-Net。O-Net 作为 MTCNN 最终的输出网络,同样可以得到与 R-Net 相类似的输出结果,但是精度和准确率要高于 R-Net。P-Net 主要作用为在要检测的图片进行大量的区域建议,并将检测结果送入 R-Net,R-Net 在此基础上进行微调修正,去掉部分不合格的区域建议之后再送入 O-Net,最后 O-Net 在前两个网络的基础上进行最后的人脸及面部关键点的检测与标定。
由于前两个网络主要用来进行区域建议,因此通常面部关键点的检测仅作为损失函数的一种来帮助网络训练,在检测过程中只有 O-Net 会对图像进行面部关键点的检测与标定。