193 lines
6.2 KiB
Markdown
193 lines
6.2 KiB
Markdown
# dlib系列笔记3:人脸检测
|
||
|
||
## 效果图
|
||
|
||

|
||
|
||
## 源码
|
||
|
||
截取重要类的实现片段
|
||
具体源码参考 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;
|
||
}
|
||
}
|
||
|
||
```
|