mynote/dlib/note/dlib系列笔记3:人脸检测.md
2018-02-25 01:24:12 +08:00

193 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# dlib系列笔记3人脸检测
## 效果图
![img1](https://raw.githubusercontent.com/lightjiang/FaceRecognize/master/results/others/1.png)
## 源码
截取重要类的实现片段
具体源码参考 https://github.com/lightjiang/FaceRecognize.git
- base.py
``` python
class Base(object):
base_path = BASEPATH
def __init__(self):
self.img = None
self.img_path = ''
def load_img(self, path, relative=True, flags=cv2.IMREAD_COLOR):
# 自动从web加载图片
if path.startswith('http'):
path = self.download_web_img(path)
img_path = path
if relative:
path = os.path.join(self.base_path, path)
if os.path.exists(path):
res = cv2.imread(path, flags=flags)
# 转换图片通道, opencv默认bgr格式dlib需要rgb格式
self.img = cv2.cvtColor(res, cv2.COLOR_BGR2RGB)
self.img_path = img_path
return self.img
else:
raise FileNotFoundError(path)
def download_web_img(self, url):
path = 'data/auto_download_img/%s.jpg' % uuid.uuid1()
# 复制的百度图片链接有时会下载异常
request.urlretrieve(url, path)
print('download complete')
return path
def save_img(self, img, path, relative=True):
if relative:
path = os.path.join(self.base_path, path)
cv2.imwrite(path, cv2.cvtColor(img, cv2.COLOR_RGB2BGR))
def add_marks(self, pos, color=None):
# 在self.img 上添加标记
if isinstance(pos, tuple):
pos = [pos]
elif isinstance(pos, list):
pos = pos
else:
raise AttributeError
if not color:
color = (0, 255, 0)
for p in pos:
cv2.circle(self.img, p, 2, color, 1)
def add_faces(self, faces, show_score=True, color=None, add_text=None):
# 在self.img 上添加脸部识别框
if isinstance(faces, dict):
faces = [faces]
elif isinstance(faces, list):
faces = faces
else:
raise AttributeError
for face in faces:
rect = face['position']
if not color:
color = (255, 0, 0)
cv2.rectangle(self.img, (rect.left(), rect.top()), (rect.right(), rect.bottom()), color, 3)
if show_score and 'score' in face:
score = face['score']
width = rect.right() - rect.left()
cv2.putText(self.img, str(round(score, 3)), (rect.left() + 10, rect.bottom() - 10), cv2.FONT_HERSHEY_SIMPLEX, width/120,
(255, 255, 255), 1)
if add_text:
width = rect.right() - rect.left()
cv2.putText(self.img, str(add_text), (rect.left() + 10, rect.bottom() - 10),
cv2.FONT_HERSHEY_SIMPLEX, width / 120,
(255, 255, 255), 1)
```
- face_detector.py
``` python
class FaceDetector(Base):
"""
based on HOG
"""
def __init__(self):
self.face_detector = dlib.get_frontal_face_detector()
super().__init__()
def detect_face(self, log_status=True):
if self.img is None:
raise AttributeError('please load img before detect')
t = time.time()
dets, scores, idx = self.face_detector.run(self.img, 1, -1)
res = []
for index, face in enumerate(dets):
temp = {
'id': str(uuid.uuid1()),
'position': face,
'score': scores[index],
'src': self.img_path
}
if scores[index] > 0:
res.append(temp)
if log_status:
print("Detecting faces takes: {}s\nNumber of faces detected: {}".format(time.time() - t, len(res)))
return res
def detect_faces_from_imgs(self, imgs: list):
t = time.time()
res = []
for img_path in imgs:
self.load_img(img_path)
res += self.detect_face(log_status=False)
self.img = None
print("Detecting faces takes: {}s\nNumber of faces detected: {}".format(time.time() - t, len(res)))
return res
```
- cpp_src/face_detector.cpp
``` cpp
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
#include <dlib/opencv.h>
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include "mybase.hpp"
using namespace dlib;
using namespace std;
// ----------------------------------------------------------------------------------------
int main(int argc, char **argv)
{
try
{
if (argc == 1)
{
cout << "Give some image files as arguments to this program." << endl;
return 0;
}
frontal_face_detector detector = get_frontal_face_detector();
// Loop over all the images provided on the command line.
for (int i = 1; i < argc; ++i)
{
cout << "processing image " << argv[i] << endl;
cv::Mat image;
image = cv::imread(argv[i], cv::IMREAD_COLOR);
dlib::cv_image<rgb_pixel> img(image);
std::vector<rectangle> dets = detector(img);
cout << "Number of faces detected: " << dets.size() << dets[0].left() <<dets[1] << image.size() << endl<< image;
for (auto temp_point: dets){
cout << temp_point<< temp_point.left() <<endl;
mark_face(image, temp_point);
// cv::rectangle(image, cv::Point(temp_point.left(), temp_point.top()), cv::Point(temp_point.right(), temp_point.bottom()),cv::Scalar(255,0,0),1,1,0);
}
// cv::rectangle(image, cv::Point(dets[0][0][0], dets[0][0][1]));
cv::namedWindow("Display window", cv::WINDOW_AUTOSIZE); // Create a window for display.
cv::imshow("Display window", image); // Show our image inside it.
cv::waitKey(0); // Wait for a keystroke in the window
}
}
catch (exception &e)
{
cout << "\nexception thrown!" << endl;
cout << e.what() << endl;
}
}
```