转载自:https://blog.csdn.net/jobbofhe/article/details/80245366
1. 环境部署
- 参考之前的文章:
https://blog.csdn.net/jobbofhe/article/details/78815944
https://blog.csdn.net/jobbofhe/article/details/79386160
搭建环境这件事,我想说没有一蹴而就的事情,别人的方案再详细(更何况常常完成之后写的方案总是概要的),自己在执行的时候也可能有不同的情况,所以认真对待过程中出现的每一个问题,一步一步解决,不要怕出错,一旦出错,这个时候正式培养解决问题的能力的时候。
2. 代码流程
- 主要接口描述
#1. 初始化检测器,
frontal_face_detector detector = get_frontal_face_detector();
#2. 加载已训练好的模型
deserialize("shape_predictor_5_face_landmarks.dat") >> sp;
deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;
#3. 加载图片
matrix<rgb_pixel> img;
#将图片数据格式转为像素矩阵
load_image(img, "name.jpg");
#4. 检测图片中人脸位置
#这里将得到图片所有中人脸的位置坐标
std::vector<rectangle> dets = detector(img);
#5 根据检测的人脸位置坐标,提取人脸特征值
std::vector<matrix<rgb_pixel>> faces;
for(unsigned long j = 0; j < dets.size(); j++)
{
auto shape = sp(img, dets[j]);
matrix<rgb_pixel> face_chip;
extract_image_chip(img, get_face_chip_details(shape,150,0.25), face_chip);
faces.push_back(move(face_chip));
}
#6. 使用DNN网络接口,将每一张人脸转为128维的特征值向量
std::vector<matrix<float,0,1>> face_descriptors = net(faces);
#7. 比较不同图片128维向量之间的距离
length(face_descriptors[i]-face_descriptors[j])
#距离越小说明人脸特征越接近,也就是同一个人的概率更大
说明:
- 在实际应用中,以上流程是通用的,唯一不同就是当我们选取不同的模型的时候,需要响应的修改模型和网络结构;
- 检测的数据除了不同格式的通篇之外,还可以是YUV等其他格式的数据这个时候就需要响应的修改保存像素值的数据结构。
3. YUV转matrix
从摄像头获取视频流,取帧得到YUV数据,由于dlib的源码中是直接加载jpg图片,转成matrix,这样会花去很多时间,YUV数据比Jpg小,所以在这里将YUV数据出入,并转换成matrix数据格式。
/********************************************************************************
功能 : YUV数据转转换为matrix
输入参数 : YUV数据,图片高,宽,补位,格式
返回值 : matrix<rgb_pixel>, 图片YUV数据转换成matrix 格式返回
*********************************************************************************/
matrix<rgb_pixel> yuv_2_matrix(
unsigned char * yuvData, int iHeight,
int iWidth, int iStride, int iFormat
)
{
matrix<rgb_pixel> img;
img.set_size(iHeight, iWidth);
if(NULL == yuvData )
{
cout << "YUV data error, Parameter is NULL !" << endl;
exit(1);
}
int yLen = iHeight*iWidth;
//int uLen = iHeight*iWidth/2;
//int vLen = uLen;
unsigned char *yData = new unsigned char [yLen];
//int *uData = new int[uLen];
//int *vData = new int[vLen];
for (int i = 0; i < iHeight * iWidth; i++)
{
yData[i] = yuvData[i];
}
int k = 0;
for (int i = 0; i < iHeight; i++)
{
for (int j = 0; j < iWidth; j++, k++)
{
rgb_pixel p((unsigned char )yData[k], (unsigned char )yData[k],
(unsigned char )yData[k]);
/* p->red = a;
p->green = a;
p->blue = a;
*/
img(i, j) = p;
}
}
delete yData;
return img;
}
说明一下编译,是生成一个.so文件
cmake_minimum_required(VERSION 2.8.12)
project(project_name)
add_compile_options(-std=c++11)
SET(CMAKE_CXX_FLAGS "-fPIC")
SET(CMAKE_C_FLAGS "-fPIC")
# dlib自身依赖,重要
add_subdirectory(../dlib dlib_build)
add_library(face_recog SHARED face_recog.cpp)
target_link_libraries(face_recog dlib::dlib)
- 注意:
- 在实际写代码过程中,在理解了整个流程之后,最重要的的事情就是了解,Dlib提供的数据结构。
参考资料
北京大学Dlib group
http://net.pku.edu.cn/dlib/
Windows 环境,Dlib使用
http://blog.csdn.net/longji/article/category/7160812/
人脸识别领域最重要的数据集合是lfw
http://vis-www.cs.umass.edu/lfw/
模型地址:
http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2
http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2