Dlib

649 阅读4分钟

官网地址

dlib.net/

Ubuntu下编译dlib静态库(.a)

下载官方dlib库,解压

 cd dlib-19.20
 mkdir build
 cd build
 cmake ..
 cmake --build . --config Release

Ubuntu下编译dlib动态库(.so)

官方文档中,dlib编译后的结果只有静态库dlib.a,编译动态库把-DBUILD_SHARED_LIBS=ON 开关打开

 cd dlib-19.20
 mkdir build
 cd build
 cmake -DBUILD_SHARED_LIBS=ON ..
 cmake --build . --config Release

Android 集成Dlib

下载官方dlib库,解压,复制dlib-19.20下的dlib目录到Android项目目录中,这里我新建了一个cpp/include目录,cpp和Java同级,

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11")
#dlib
set(pathToDlib ${CMAKE_SOURCE_DIR}/src/main/cpp/include/)
include(${pathToDlib}/dlib/cmake)
add_library( # Sets the name of the library.
        native-lib    #.so库名 可自定义
        SHARED        # 生成动态库SHARED,生成静态库STATIC 
        src/main/cpp/native-lib.cpp  #相关的cpp文件
        )
find_library(         # 可在cpp中打印Android日志,cout无法显示
        log-lib
        log)
target_link_libraries(
        native-lib
        dlib
        ${log-lib})  
  • 遇到的错误
error: "DLIB_NO_GUI_SUPPORT is defined so you can't use the GUI code.  Turn DLIB_NO_GUI_SUPPORT off if you want to use it."

因为Android平台没有相关的GUI界面显示,也没有相关的库文件,所以无法加载 打开cpp/include/dlib文件夹,找到CmakeLists.txt,找到以下代码,将其注释 将所有用到gui_widgets.h,gui_core/xlib.h,gui_core.h,drawable.h,gui_core_kernel_2.h的地方注释掉

简单移植dlib和opencv到Androd平台进行人脸检测

blog.csdn.net/a568478312/…

使用Cmake在NDK环境下移植Dlib库

blog.csdn.net/u012525096/…

  • 环境 SDK Manager中SDK Tools安装 Cmake(编译工具),NDK(环境)
  • 获取dlib源码 下载Dlib源码,官网地址:dlib.net/
  • 项目中添加dlib 解压缩Dlib后,得到dlib-XX.X目录,进入该目录,复制dlib文件夹(该文件下都是源码)
  • 配置CmakeList
#需求的Cmake最小版本号
cmake_minimum_required(VERSION 3.4.1)

#设置变量 dlib的路径
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../distribution)
set(pathToDlib ${CMAKE_SOURCE_DIR}/src/main/)

#包含dlib的CmakeLists.txt
include(${pathToDlib}/dlib/cmake)

#编译成library,native-my是库的名字、SHARED是动态库、源码(自己写的JNI文件,可以有多个)
add_library(native-my SHARED
            src/main/cpp/native-test.cpp)
            
#设置输出库文件的位置
set_target_properties(native-my PROPERTIES
                      LIBRARY_OUTPUT_DIRECTORY
                      ${distribution_DIR}/libs/${ANDROID_ABI})
                      
#库需要链接(依赖)的其他的库,一起打包成第一个参数的名字下面都是链接的库。
#这里的${CMAKE_SOURCE_DIR}的值,若有多个则指向顶级CMakeLists.txt的路径。
target_link_libraries(native-my
                      dlib::dlib
                      log)
#设置Debug/Release的编译选项,Dlib的Debug版本很慢。
SET(CMAKE_BUILE_TYPE "RELEASE")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
SET(CMAKE_BUILE_TYPE "DEBUG")
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
 
  • 关联 在build.gradle中关联上该CMakeLists.txt。打开app模块下的build.gradle,内容增加如下:
externalNativeBuild {
            cmake {
                arguments '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_TOOLCHAIN=clang', 
                        '-DANDROID_STL=c++_shared', 
                        '-DCMAKE_BUILD_TYPE=Release ..'
                cppFlags "-std=c++11 -O3"
            }
        }
        ndk {
            abiFilters 'armeabi'
        }

arguments设置cmake的平台,编译器,STL版本库的支持,Release模式(dlib必须使用的东西)。 cppFlags设置了编译参数(一些支持)。 ndk.abiFilters设置了编译出的不同平台库文件过滤器,使用对应CPU的平台,可以缩小APK体积。

build.gradleandroid下增加(与defaultConfig并列):

 externalNativeBuild {
        cmake {
            path 'CMakeLists.txt'
        }
    }

增加jniLibs源文件夹,可以打包入APK(与defaultConfig并列)

  sourceSets {
        main {
            jniLibs.srcDirs = ['../distribution/libs']
        }
    }

整个build.gradle内容如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.shen.testdlib0102"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                arguments '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_shared', '-DCMAKE_BUILD_TYPE=Release ..'
                cppFlags "-std=c++11 -O3"
            }
        }
        ndk {
            abiFilters 'armeabi'
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path 'CMakeLists.txt'
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['../distribution/libs']
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

build/Rebuild或者make module app一下,dlib被当做了静态库使用,native-my是我们自己写的JNI编译成共享库,而JniLibs中有我们JNI代码生成的so文件。

  • 问题 android平台没有相关的GUI界面显示,也没有相关的库,需要自己注释掉
  • More than one file was found with OS independent path ‘XXXXX’ 在出现问题的module中的build.gradle的android下(与defaultConfig同级别)加上如下代码:
packagingOptions {
        pickFirst 'lib/armeabi/libnative-my.so'
    }

该原因由于CmakeLists中设置了SO库文件的输出目录,在Build.gradle中指定了JniLibs.srcDir,又由于在Build/intermediates/cmake中有中间文件。AS默认会自动复制临时目录的库文件到APK,但由指定了预编译的库,造成SO库文件重复,AS不知道去复制哪个,该句话就是指定优先级。

实现人脸特征点检测全过程

  • 封装成单例类:

blog.csdn.net/KayChanGEEK…

  • 加快Dlib的面部地标检测器的速度

www.learnopencv.com/speeding-up…

  • 官网三个例子

blog.csdn.net/ouyangying1…

人脸Landmark检测速度优化

zhuanlan.zhihu.com/p/36456092

dlib.net/faq.html#Wh…

www.njrjy.com/products/41…

  • 安装Release版本Dlib:
cd dlib-19.19
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=ON -DDLIB_USE_LAPACK=1 .. -DUSE_AVX_INSTRUCTION=ON -DUSE_SSE4_INSTRUCTIONS=ON
cmake --build . --config Release
sudo make install
  • 安装Dlib之后需要修改的:
/usr/local/include/dlib/opencv/cv_image.h
IplImage temp = cvIplImage(img);

  • 人脸Landmark检测速度优化
cv::Mat temp2;
cv::resize(image, temp2,cv::Size(width/2,height/2));
cv_image<bgr_pixel> cimg2(temp2);
std::vector<rectangle> dlibfaces = detector(cimg2);
for (unsigned long i = 0; i < dlibfaces.size(); ++i) {
dlibfaces[i].set_top(dlibfaces[i].top()*2);
dlibfaces[i].set_bottom(dlibfaces[i].bottom() * 2);
dlibfaces[i].set_left(dlibfaces[i].left()*2);
dlibfaces[i].set_right(dlibfaces[i].right()*2);
}

1:N 人脸识别

//1:N 人脸识别
string FaceRecognizer::recognize(string testImagePath, double similar)
{
    string facesID;
    std::vector<string> results = recognizeFaceByCamera(testImagePath);
    for (std::size_t i = 0; i < results.size(); ++i) {
        matrix<float> testFace = face_base64_decode(results[i]);
        mongocxx::client conn{mongocxx::uri{}};
        auto collection = conn["testdb"]["testcollection"];//可以理解成为testdb数据库的testcollection表
        double min = 1;
        //查询testdb数据库的testcollection集合中的所有文档
        auto cursor = collection.find({});
        for (auto&& doc : cursor) {
            string features = doc["features"].get_utf8().value.to_string();
//        facesID = doc["faceId"].get_utf8().value.to_string();
//        cout << "facesID" << facesID << endl;
            matrix<float> faceLibrary = face_base64_decode(features);
            double distance = length(testFace - faceLibrary);
            if (distance < min)
            {
                min = distance;
                facesID = doc["faceId"].get_utf8().value.to_string();
            }
        }
    if(min < similar) {
        cout << "similar :" << facesID << endl;
        return facesID;
    }else {
        return "NULL";
    }
}

提取人脸特征点

//提取人脸特征点
string FaceRecognizer::recognizeFace(string imagePath,bool isPicture) {
    cout << " the path of test picture:" << imagePath << endl;
    matrix<rgb_pixel> imgtest;            //定义dlib型图片,彩色
    std::vector<matrix<rgb_pixel>> faces_test;
    load_image(imgtest, imagePath);
​
    matrix<rgb_pixel> img;
    cv::Mat image = cv::imread(imagePath);
    array2d< bgr_pixel> arrimg(image.rows, image.cols);
    dlib::assign_image(imgtest, cv_image<rgb_pixel>(image));
​
    for (auto face_test : detector(imgtest))
    {
        auto shape_test = sp(imgtest, face_test);
        matrix<rgb_pixel> face_chip_test;
        extract_image_chip(imgtest, get_face_chip_details(shape_test, 150, 0.25), face_chip_test);
        faces_test.push_back(move(face_chip_test));
    }
//    cout << "The vector of picture " <<imagepath << "  is:" << trans(face_test_descriptors[0]) << endl;//打印该人脸的标签和特征向量
    std::vector<dlib::rectangle> dets_test = detector(imgtest);
    std::vector<matrix<float, 0, 1>> face_test_descriptors = net(faces_test);
    face_base64_encode(face_test_descriptors[0]);
    return face_base64_encode(face_test_descriptors[0]);
}

人脸检测

  • 需要的模型:

dlib.net/files/dlib_…

dlib.net/files/shape…

www.cnblogs.com/spoorer/p/7…

blog.csdn.net/sinat_35907…

//提取人脸特征点
string FaceRecognizer::recognizeFace(string imagePath,bool isPicture) {
    cout << " the path of test picture:" << imagePath << endl;
    matrix<rgb_pixel> imgtest;            //定义dlib型图片,彩色
    std::vector<matrix<rgb_pixel>> faces_test;
    load_image(imgtest, imagePath);
​
    matrix<rgb_pixel> img;
    cv::Mat image = cv::imread(imagePath);
    array2d< bgr_pixel> arrimg(image.rows, image.cols);
    dlib::assign_image(imgtest, cv_image<rgb_pixel>(image));
​
    for (auto face_test : detector(imgtest))
    {
        auto shape_test = sp(imgtest, face_test);
        matrix<rgb_pixel> face_chip_test;
        extract_image_chip(imgtest, get_face_chip_details(shape_test, 150, 0.25), face_chip_test);
        faces_test.push_back(move(face_chip_test));
    }
//    cout << "The vector of picture " <<imagepath << "  is:" << trans(face_test_descriptors[0]) << endl;//打印该人脸的标签和特征向量
    std::vector<dlib::rectangle> dets_test = detector(imgtest);
    std::vector<matrix<float, 0, 1>> face_test_descriptors = net(faces_test);
    face_base64_encode(face_test_descriptors[0]);
    return face_base64_encode(face_test_descriptors[0]);
}