部分资料来源于 opencv基于DNN的人脸检测
opencv的base里是有dnn这个深度学习文件的。目录:...opencv\sources\samples\dnn
通过download_models.py下载相关net文件
当然有可能因为网络原因不能下载,那么可以去github上下载,我也会贴出来
face_detector-深度学习文档类资源
blobFromImage预处理
在进行深度学习或者图片分类时,blobFromImage主要是用来对图片进行预处理。从图像创建 4 维 blob。可选择从中心调整大小和裁剪图像,减去平均值,比例值按比例因子,交换蓝色和红色通道。
包含两个主要过程:
- 整体像素值减去平均值(mean)
- 通过缩放系数(scalefactor)对图片像素值进行缩放
blobFromlmage(
cv:InputArray image,
double scalefactor = (1.0), //输出图像的大小空间大小
const cv:Size &size =c::Size0, //图像值的比例因子乘数。
const cx::Scalar &mean = cv:Scalar0,
/*需要将图片整体减去的平均值,
如果我们需要对RGB图片的三个通道分别减去不同的值,
那么可以使用3组平均值,如果只使用一组,那么就默认对三个通道减去一样的值。
减去平均值(mean):为了消除同一场景下不同光照的图片,对我们最终的分类或者神经网络的影响,
我们常常对图片的R、G、B通道的像素求一个平均值,
然后将每个像素值减去我们的平均值,
这样就可以得到像素之间的相对值,就可以排除光照的影响。
*/
bool swapRB = false, //swapRB 标志,表示需要在 3 通道图像中交换第一个和最后一个通道。
boolcrop = false, //裁剪标志,指示在调整大小后是否裁剪图像
int ddepth= 5 //ddepth 输出 blob 的深度。选择 CV 32F 或 CV 8U。
)
setInput
void cv::dnn::Net::setInput (
InputArray blob,
const String & name = "",
double scalefactor = 1.0,
const Scalar & mean = Scalar() )
- blob:一个新的blob。 应该有CV_32F或CV_8U深度。就是上文中介绍的blobFromImage的返回值
- name:输入图层的名称。
- scalefactor:可选的标准化比例。
- mean:一个可选的平均减法值。
capture.read(frame);
flip(frame, frame, 1); //翻
if (frame.empty()) {
break;
}
Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104, 177, 123), false, false); //深度学习的预处理 均值Scalar(104, 177, 123) 不进行通道交换
net.setInput(blob);// NCHW number、chanel、high、weigh
Mat probs = net.forward(); // 特征返回
Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>()); //
// 解析结果
for (int i = 0; i < detectionMat.rows; i++) {
float confidence = detectionMat.at<float>(i, 2);
if (confidence > 0.5) {
int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);
Rect box(x1, y1, x2 - x1, y2 - y1);
rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);
}
}
imshow("人脸检测演示", frame);
int c = waitKey(16);
if (c == 27) { // 退出
break;
}
}