opencv基于DNN的⼈脸检测
from:
opencv3.4 版之前⾃带的⼈脸检测器是基于Haar+Adaboost的,速度还可以,但是检出率很低,误检也很多,脸的⾓度稍⼤就检不出来,还经常会把⼀些乱七⼋糟的东西当做⼈脸,实在不敢恭维。好在随着深度学习领域的发展,涌现了⼀⼤批效果相当不错的⼈脸检测算法,⽐如MTCNN,给了我们更多施展的空间。看看下⾯这图就是基于其检测出来的,看着是不是很震撼呢?
MTCNN效果着实不错,但其是基于caffe训练的,caffe可是以配置繁琐著称的,⼤⼤⼩⼩依赖库就有10⼏个,每个⼜有好⼏个版本,版本间的不兼容⽐⽐皆是,初学者没个把星期基本是配不好的,这⽆形间加⼤了普及的进度,好在有⼈做了⼀整套MTCNN在各个平台上的部署(),⼤⼤简化了所需的⼯作量。
opencv发布了3.4版本,主要增强了dnn模块,特别是添加了对faster-rcnn的⽀持,并且带有openCL加速,效果还不错。
我主要测试了下其中的resnetface⽰例,效果还不错,除了速度上有些慢之外,基本上是向MTCNN看齐了。
以face_detector Caffe模型为例。(位于${OPENCV_DIR}\sources\samples\dnn\face_detector)
⼀般需要两个⽂件:1)模型参数    2)模型配置⽂件即模型框架
res10_300x300_ssd_iter_140000_fp16.caffemodel
deploy.prototxt
在caffe中,模型定义在prototxt⽂件中,⽂件中定义了每层的结构信息。
rectangle函数opencv例如我的opencv路径是:D:\Program Files\OpenCV\opencv\sources\samples\dnn\face_detector,打开之后:
⾥⾯有个,使⽤pycharm执⾏下就可以⾃动下载模型(2种模型)了。或者直接点击下⽅的链接直接下载:
1、'res10_300x300_ssd_iter_140000_fp16.caffemodel'
2、'opencv_face_detector_uint8.pb'
下载的⽂件放在face_detector⽬录下,如图:
python版代码如下:
#coding=utf-8
import numpy as np
import cv2,os,time
def show_detections(image,detections):
h,w,c=image.shape
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence >0.6:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
(0, 255,0), 1)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)
return image
def detect_img(net,image):
blob = cv2.dnn.size(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
net.setInput(blob)
start=time.time()
detections = net.forward()
end=time.time()
print(end-start)
return show_detections(image,detections)
def test_dir(net,dir="images"):
files=os.listdir(dir)
for file in files:
filepath=dir+"/"+file
img=cv2.imread(filepath)
showimg=detect_img(net,img)
cv2.imshow("img",showimg)
cv2.waitKey()
def test_camera(net):
cap=cv2.VideoCapture(0)
while True:
ret,ad()
if not ret:
break
showimg=detect_img(net,img)
cv2.imshow("img",showimg)
cv2.waitKey(1)
if __name__=="__main__":
net = adNetFromCaffe("deploy.prototxt","res10_300x300_ssd_iter_140000_fp16.caffemodel")
#net =adNetFromTensorflow("opencv_face_detector_uint8.pb","opencv_face_detector.pbtxt")
#test_dir(net)
test_camera(net)
其⽀持caffe和tensorflow两种模型,速度在35毫秒左右(CPU:i7 4910MQ@2.5GHz,4核,占⽤率60%) C++版代码如下:
#include <iostream>
#include <cstdlib>
#include<opencv2\dnn\dnn.hpp>
#include<opencv2\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace cv::dnn;
using namespace std;
const size_t inWidth = 300; //output image size
const size_t inHeight = 300;
const double inScaleFactor = 1.0;
const Scalar meanVal(104.0, 117.0, 123.0);
int main(int argc, char** argv)
{
float min_confidence = 0.5;
String modelConfiguration = "D:\\Program Files\\OpenCV\\opencv\\sources\\samples\\dnn\\face_detector\\deploy.prototxt";
String modelBinary = "D:\\Program Files\\OpenCV\\opencv\\sources\\samples\\dnn\\face_detector\\res10_300x300_ssd_iter_140000_fp16.caffemodel"; //! [Initialize network]
dnn::Net net = readNetFromCaffe(modelConfiguration, modelBinary);//Reads a network model stored in Caffe model in memory
//! [Initialize network]
if (pty())
{
cerr << "Can't load network by using the following files: " << endl;
cerr << "prototxt:  " << modelConfiguration << endl;
cerr << "caffemodel: " << modelBinary << endl;
cerr << "Models are available here:" << endl;
cerr << "<OPENCV_SRC_DIR>/samples/dnn/face_detector" << endl;
cerr << "or here:" << endl;
cerr << "github/opencv/opencv/tree/master/samples/dnn/face_detector" << endl;
exit(-1);
}
//VideoCapture cap(0);//打开摄像头
VideoCapture cap("C:\\Users\\liuzhe\\Desktop\\face.avi");
if (!cap.isOpened())
{
cout << "Couldn't open camera : " << endl;
return -1;
}
for (;;)//死循环
{
Mat frame;
cap >> frame; // get a new frame from camera/video or read image
if (pty())
{
waitKey();
break;
}
if (frame.channels() == 4)
cvtColor(frame, frame, COLOR_BGRA2BGR);
//! [Prepare blob]
Mat inputBlob = blobFromImage(frame, inScaleFactor,
Size(inWidth, inHeight), meanVal, false, false); //Convert Mat to batch of images
//! [Prepare blob]
//! [Set input blob]
net.setInput(inputBlob, "data"); //set the network input
//! [Set input blob]
//! [Make forward pass]
/
/compute output,这是⼀个4D数,rows and cols can only hold 2 dimensions, so they are not used here, and set to -1
Mat detection = net.forward("detection_out");  //! [Make forward pass]
vector<double> layersTimings;
double freq = getTickFrequency() / 1000;//⽤于返回CPU的频率。get Tick Frequency。这⾥的单位是秒,也就是⼀秒内重复的次数。  double time = PerfProfile(layersTimings) / freq;
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());//101*7矩阵
ostringstream ss;
ss << "FPS: " << 1000 / time << " ; time: " << time << " ms";
putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));
float confidenceThreshold = min_confidence;
for (int i = 0; i < ws; i++)
{
float confidence = detectionMat.at<float>(i, 2);      //第⼆列存放可信度
if (confidence > confidenceThreshold)//满⾜阈值条件
{
//存放⼈脸所在的图像中的位置信息
int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * ls);
int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * ws);
int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * ls);
int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * ws);
Rect object((int)xLeftBottom, (int)yLeftBottom,//定义⼀个矩形区域(x,y,w,h)
(int)(xRightTop - xLeftBottom),
(int)(yRightTop - yLeftBottom));
rectangle(frame, object, Scalar(0, 255, 0));//画个边框
ss.str("");
ss << confidence;
String conf(ss.str());
String label = "Face: " + conf;
int baseLine = 0;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom - labelSize.height),
Size(labelSize.width, labelSize.height + baseLine)),
Scalar(255, 255, 255), CV_FILLED);
putText(frame, label, Point(xLeftBottom, yLeftBottom),
FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));
}
}
cv::imshow("detections", frame);
if (waitKey(1) >= 0) break;
}
return 0;
}
代码地址:
核⼼函数介绍
主要涉及函数有以下⼏个:
readNetFromCaffe
blobFromImage
setInput
forward
1、blobFormImage
函数原型

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。