糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 在windows和linux下使用cmake dlib编译人脸识别动态链接库

在windows和linux下使用cmake dlib编译人脸识别动态链接库

时间:2021-06-17 16:23:16

相关推荐

在windows和linux下使用cmake dlib编译人脸识别动态链接库

在windows和linux下使用cmake、dlib编译人脸识别动态链接库

开发人脸识别应用时,由于前端设备及操作系统种类繁多,如果选择在侵短实现识别功能适配工作较为繁琐,故计划将人脸识别功能在后端实现从而统一为应用提供服务。需要对dlib进行封装以供其他语言调用。

前提:cmake安装及dlib的编译

使用cmake将dlib编译成静态库lib文件,或者动态链接库(windows上为dll,linux上为so)。

开发环境

windows

win11

cmake-3.32.2

Microsoft Visual Studio

linux

redhat7.6

cmake-3.25.2

gcc-9.3.1

CMakeLists.txt 及 c++代码

CMakeLists.txt

CMAKE_MINIMUN_REQUIRED(VERSION 2.8.4)PROJECT(facerecog)SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -DDLIB_JPEG_SUPPORT")IF(UNIX)INCLUDE_DIRECTORIES(/root/dlib-19.24)ELSE()ADD_DEFINITIONS(-DFRDLL_EXPORTS)INCLUDE_DIRECTORIES(D:/FaceRecognize/dlib-19.24)ENDIF()IF(UNIX)LINK_DIRECTORIES(/root/dlib-19.24/build/dlib)ELSE()LINK_DIRECTORIES(D:/FaceRecognize/dlib-19.24/build/dlib/Release)ENDIF()#ADD_EXECUTABLE(facerecog dlib_test.cpp)ADD_LIBRARY(facerecog SHARED facerecoglib.h facerecoglib.cpp)IF(UNIX)#TARGET_LINK_LIBRARIES(facerecog dlib)TARGET_LINK_LIBRARIES(facerecog libdlib.so)TARGET_LINK_LIBRARIES(facerecog pthread)ELSE()TARGET_LINK_LIBRARIES(facerecog dlib19.24.0_release_64bit_msvc1900.lib)ENDIF()

facerecoglib.h

#ifndef FACERECOGLIB_H#define FACERECOGLIB_H#ifdef _WINDOWS#ifdef FRDLL_EXPORTS#define FRDLL_API __declspec(dllexport)#else#define FRDLL_API __declspec(dllimport)#endif#else#define FRDLL_API#endifextern "C"{// 功能:初始化特征库,读取并保存基准图像文件夹中所有人脸特征值及特征信息(文件FRDLL_API int fg_init(const char* featurepicdir,float threshold);// 功能:识别路径未picpath的图片,返回对应的人员信息FRDLL_API char* fg_recog(const char* picpath);// 功能:识别是否匹配特定人脸特征FRDLL_API int fg_recogspecial(const char* picpath,const char* featureinfo);// 功能:插入新特征值到特征库FRDLL_API int fb_insertfeature(const char* picpath);// 功能:删除指定的特征值及特征信息FRDLL_API int fb_deletefeature(const char* featureinfo);}#endif

facerecoglib.cpp

//尽量减少对其他库的依赖,未使用图形及opencv支持#include <algorithm>#include <dlib/dnn.h>#include <dlib/clustering.h>#include <dlib/image_processing/frontal_face_detector.h>#include <dlib/image_io.h>#include <iostream>#include <vector>#include <string>#include <map>#ifdef _WINDOWS#include "io.h"#else#include <dirent.h>#endif // _WINDOWS#include "facerecoglib.h"using namespace dlib;using namespace std;template <template <int, template<typename>class, int, typename> class block, int N, template<typename>class BN, typename SUBNET>using residual = add_prev1<block<N, BN, 1, tag1<SUBNET>>>;template <template <int, template<typename>class, int, typename> class block, int N, template<typename>class BN, typename SUBNET>using residual_down = add_prev2<avg_pool<2, 2, 2, 2, skip1<tag2<block<N, BN, 2, tag1<SUBNET>>>>>>;template <int N, template <typename> class BN, int stride, typename SUBNET>using block = BN<con<N, 3, 3, 1, 1, relu<BN<con<N, 3, 3, stride, stride, SUBNET>>>>>;template <int N, typename SUBNET> using ares = relu<residual<block, N, affine, SUBNET>>;template <int N, typename SUBNET> using ares_down = relu<residual_down<block, N, affine, SUBNET>>;template <typename SUBNET> using alevel0 = ares_down<256, SUBNET>;template <typename SUBNET> using alevel1 = ares<256, ares<256, ares_down<256, SUBNET>>>;template <typename SUBNET> using alevel2 = ares<128, ares<128, ares_down<128, SUBNET>>>;template <typename SUBNET> using alevel3 = ares<64, ares<64, ares<64, ares_down<64, SUBNET>>>>;template <typename SUBNET> using alevel4 = ares<32, ares<32, ares<32, SUBNET>>>;using anet_type = loss_metric<fc_no_bias<128, avg_pool_everything<alevel0<alevel1<alevel2<alevel3<alevel4<max_pool<3, 3, 2, 2, relu<affine<con<32, 7, 7, 2, 2,input_rgb_image_sized<150>>>>>>>>>>>>>;frontal_face_detector detector;shape_predictor predictor;anet_type net;float frthreshold = 0.4;std::map<std::string,matrix<float, 0, 1>> mapFeature;static char retstr[255];//返回图像img中所有人脸特征值std::vector<matrix<float, 0, 1>> GetFaceFeature(matrix<rgb_pixel> img){std::vector<matrix<float, 0, 1>> features;std::vector<dlib::rectangle> dets = detector(img); std::vector<matrix<rgb_pixel>> faces;for (auto const& det : dets){auto shape = predictor(img, det);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));}std::vector<matrix<float, 0, 1>> face_descriptors = net(faces);for (auto const& feature : face_descriptors){features.push_back(feature);}return features;}#读取strfeaturepicdir路径下所有图片作为识别基准数据int CreateDataset(std::string strfeaturepicdir){mapFeature.clear();std::vector<std::string> arrFileNames; //图片完整路径std::vector<std::string> arrLabels; //图片名称,无扩展名,作为识别输出信息#ifdef _WINDOWS_finddata_t file;intptr_t HANDLE;std::string strdir = strfeaturepicdir + "\\*.*";HANDLE = _findfirst(strdir.c_str(), &file);if (HANDLE == -1L){return -1;}do {//判断是否有子目录 if (file.attrib & _A_SUBDIR == 0){std::string fileName = file.name;if (fileName.find(".jpg") != string::npos || fileName.find(".jpeg") != string::npos|| fileName.find(".bmp") != string::npos || fileName.find(".JPEG") != string::npos|| fileName.find(".JPG") != string::npos || fileName.find(".BMP") != string::npos){std::string label = fileName.find_last_of('.') == string::npos ? fileName : fileName.substr(0, fileName.find_last_of('.'));fileName = strfeaturepicdir + "\\" + fileName;arrFileNames.push_back(fileName);arrLabels.push_back(label);}}} while (_findnext(HANDLE, &file) == 0);_findclose(HANDLE);#elseDIR *dir;struct dirent *ptr;if ((dir = opendir(strfeaturepicdir.c_str())) == NULL) { return -1; }while ((ptr = readdir(dir)) != NULL) { if (ptr->d_name[0] == '.') continue; if (ptr->d_type == 8) { std::string fileName = ptr->d_name;if (fileName.find(".jpg") != string::npos || fileName.find(".jpeg") != string::npos|| fileName.find(".bmp") != string::npos || fileName.find(".JPEG") != string::npos|| fileName.find(".JPG") != string::npos || fileName.find(".BMP") != string::npos) {std::string label = fileName.find_last_of('.') == string::npos ? fileName : fileName.substr(0,fileName.find_last_of('.'));fileName = strfeaturepicdir + "//" + fileName;arrFileNames.push_back(fileName);arrLabels.push_back(label);} }}closedir(dir);#endif // _WINDOWSfor (int k = 0; k < arrFileNames.size(); k++){matrix<rgb_pixel> img;try{load_image(img, arrFileNames[k]);}catch(exception& e){cout << "\nexception thrown!" << endl;cout << e.what() << endl;return -5;}std::vector<matrix<float, 0, 1>> features = GetFaceFeature(img);if (features.size() == 0 || features.size() > 1)return -2;elsemapFeature.insert(pair<string,matrix<float, 0, 1>>(arrLabels[k],features[0]));}return mapFeature.size();}std::string GetRecogInfo(matrix<float, 0, 1> predict_value){std::string strInfo;float min_dis = 10000;for(std::map<std::string,matrix<float, 0, 1>>::iterator it = mapFeature.begin(); it != mapFeature.end(); it++){float dis = (float)length(predict_value - it->second);if (min_dis > dis){min_dis = dis;strInfo = it->first;}}if (min_dis > frthreshold)strInfo = "UNKNOWN";return strInfo;}int fg_init(const char* picdir,float threshold){frthreshold = threshold;try{detector = get_frontal_face_detector();deserialize("model//shape_predictor_68_face_landmarks.dat") >> predictor;deserialize("model//dlib_face_recognition_resnet_model_v1.dat") >> net;}catch (exception& e){cout << "\nexception thrown!" << endl;cout << e.what() << endl;return -3;}std::string strpicdir = picdir;return CreateDataset(strpicdir);}char* fg_recog(const char* picpath){if(mapFeature.size() == 0)return "NOFACEFEATURES";matrix<rgb_pixel> img;try{load_image(img, picpath);}catch(exception& e){cout << "\nexception thrown!" << endl;cout << e.what() << endl;return "CANNOTOPENIMG";}std::vector<matrix<float, 0, 1>> fsrc = GetFaceFeature(img);if(fsrc.size() == 0)return "NOSOURCEFACE";if(fsrc.size() > 1)return "MOREFACES";std::string strRet = GetRecogInfo(fsrc[0]);if (strRet.length() > 254)return "";strcpy(retstr, strRet.c_str());return retstr;}int fg_recogspecial(const char* picpath,const char* featureinfo){string strfeatureinfo = featureinfo;if(strfeatureinfo.empty())return -1;matrix<rgb_pixel> img;try{load_image(img, picpath);}catch(exception& e){cout << "\nexception thrown!" << endl;cout << e.what() << endl;return -5;}std::vector<matrix<float, 0, 1>> fsrc = GetFaceFeature(img);if(fsrc.size() > 1 || fsrc.size() == 0)return -2;if(mapFeature.count(strfeatureinfo) == 0)return -3;float dis = (float)length(fsrc[0] - mapFeature.at(strfeatureinfo));if(dis > frthreshold)return 0;elsereturn 1;}int fb_insertfeature(const char* picpath){std::string strPicPath = picpath;if(strPicPath.empty())return 0;if(mapFeature.count(strPicPath))return -1;matrix<rgb_pixel> img;try{load_image(img, strPicPath);}catch(exception& e){cout << "\nexception thrown!" << endl;cout << e.what() << endl;return -5;}std::vector<matrix<float, 0, 1>> fsrc = GetFaceFeature(img);if(fsrc.size() > 1 || fsrc.size() == 0)return -2;std::string label = fileName.find_last_of('.') == string::npos ? fileName : fileName.substr(0,fileName.find_last_of('.'));mapFeature.insert(pair<string,matrix<float, 0, 1>>(label,fsrc[0]));return 1;}int fb_deletefeature(const char* featureinfo){string strInfo = featureinfo;if(strInfo.empty())return -1;if(mapFeature.count(strInfo) == 0)return 0;mapFeature.erase(strInfo);return 1;}

命令行编译

windows

mkdir buildcd buildcmake -G "Visual Studio 14 Win64" -T host=x64 ..cmake --build . --config Release

linux

mkdir buildcd buildcmake ..cmake --build . --config Release

链接库测试

linux下可以使用nm命令查看so文件函数列表;windows下使用vs命令行下的dumpbin命令查看dll文件的函数列表。

cd 到动态链接库所在文件夹下,输入命令:

windows

dumpbin /exports facerecog.dll

linux

nm libfacerecog.so | grep fgnm libfacerecog.so | grep fb

demo

frtest.cpp

#include "facerecoglib.h"#include <string>#include <iostream>int main(){int res = fg_init("data", 0.4);if(res > 0){std::cout << "print pic path to recog person" << std::endl;std::string path;while(1){std::cin >> path;std::cout << fg_recog(path.c_str()) << std::endl;std::cout << "continue print pic path" << std::endl; }}std::cout << res << std::endl;return 0;}

编写一个简单的c++demo对动态连接库进行调用测试,demo目录中内容如图

data中保存基准图片,model保存模型,命令行运行frtest,结果如下

参考

机器学习库dlib的C++编译和使用(windows和linux)_踏莎行hyx的博客-CSDN博客_dlib c++

linux环境下利用Cmake生成动态链接库并使用实例_搞技术的火星人的博客-CSDN博客_cmake生成动态库 linux

c++人脸识别-vs + dlib19.19_zzubqh103的博客-CSDN博客_dlib人脸识别c++

如果觉得《在windows和linux下使用cmake dlib编译人脸识别动态链接库》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。