Created
December 25, 2022 21:18
-
-
Save st235/b79b04bfbd0779b248e2271fc7a2d706 to your computer and use it in GitHub Desktop.
Face recognition with Dlib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.0.0) | |
project(face_detection VERSION 0.0.1) | |
set(CMAKE_CXX_STANDARD 17) | |
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) | |
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) | |
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) | |
include(FetchContent) | |
FetchContent_Declare(dlib | |
GIT_REPOSITORY https://github.com/davisking/dlib.git | |
GIT_TAG v19.24 | |
) | |
FetchContent_MakeAvailable(dlib) | |
add_executable(face_detection main.cpp dnn_face_recognition_model.h) | |
target_link_libraries(face_detection dlib::dlib) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FACE_DETECTION_DNN_FACE_RECOGNITION_MODEL_H | |
#define FACE_DETECTION_DNN_FACE_RECOGNITION_MODEL_H | |
#include <dlib/dnn.h> | |
#include <dlib/clustering.h> | |
template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET> | |
using residual = dlib::add_prev1<block<N,BN,1,dlib::tag1<SUBNET>>>; | |
template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET> | |
using residual_down = dlib::add_prev2<dlib::avg_pool<2,2,2,2,dlib::skip1<dlib::tag2<block<N,BN,2,dlib::tag1<SUBNET>>>>>>; | |
template <int N, template <typename> class BN, int stride, typename SUBNET> | |
using block = BN<dlib::con<N,3,3,1,1,dlib::relu<BN<dlib::con<N,3,3,stride,stride,SUBNET>>>>>; | |
template <int N, typename SUBNET> using ares = dlib::relu<residual<block,N,dlib::affine,SUBNET>>; | |
template <int N, typename SUBNET> using ares_down = dlib::relu<residual_down<block,N,dlib::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 face_recognition_dnn_model = dlib::loss_metric<dlib::fc_no_bias<128,dlib::avg_pool_everything< | |
alevel0< | |
alevel1< | |
alevel2< | |
alevel3< | |
alevel4< | |
dlib::max_pool<3,3,2,2,dlib::relu<dlib::affine<dlib::con<32,7,7,2,2, | |
dlib::input_rgb_image_sized<150> | |
>>>>>>>>>>>>; | |
#endif //FACE_DETECTION_DNN_FACE_RECOGNITION_MODEL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
// Load Image | |
#include <dlib/image_io.h> | |
// Shape predictor | |
// dlib::shape_predictor | |
// landmarks: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2 | |
#include <dlib/image_processing/shape_predictor.h> | |
// Face detector | |
// dlib::frontal_face_detector | |
#include <dlib/image_processing/frontal_face_detector.h> | |
// Render face landmarks (for win overlays) | |
// dlib::render_face_detections | |
#include <dlib/image_processing/render_face_detections.h> | |
// face_recognition_dnn_model | |
#include "dnn_face_recognition_model.h" | |
// Gui | |
#include <dlib/gui_widgets.h> | |
void ShowImage(const dlib::array2d<dlib::rgb_pixel>& image) { | |
dlib::image_window win; | |
win.set_image(image); | |
// using of title creates | |
// memory leak at least on MacOS | |
// win.set_title(title) | |
win.wait_until_closed(); | |
} | |
int main(int argc, char** argv) { | |
if (argc <= 3) { | |
std::cout | |
<< "Call app with the image param" << std::endl | |
<< "./face_detection image_name" << std::endl; | |
return 1; | |
} | |
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector(); | |
dlib::shape_predictor shape_predictor; | |
// shape_predictor_68_face_landmarks.dat | |
dlib::deserialize(argv[1]) >> shape_predictor; | |
face_recognition_dnn_model face_recognition_dnn_model; | |
// dlib_face_recognition_resnet_model_v1.dat | |
dlib::deserialize(argv[2]) >> face_recognition_dnn_model; | |
dlib::image_window win; | |
for (int i = 3; i < argc; i++) { | |
dlib::array2d<dlib::rgb_pixel> image; | |
dlib::load_image(image, argv[i]); | |
dlib::pyramid_up(image); | |
std::vector<dlib::matrix<dlib::rgb_pixel>> face_images; | |
std::vector<dlib::rectangle> face_rectangles = detector(image); | |
std::vector<dlib::full_object_detection> faces_landmarks; | |
for (const auto& face_rectangle: face_rectangles) { | |
dlib::full_object_detection landmarks = shape_predictor(image, face_rectangle); | |
faces_landmarks.push_back(landmarks); | |
dlib::matrix<dlib::rgb_pixel> face_image; | |
dlib::extract_image_chip(image, dlib::get_face_chip_details(landmarks, 150, 0.25), face_image); | |
face_images.push_back(std::move(face_image)); | |
} | |
win.clear_overlay(); | |
win.set_image(image); | |
// add red faces rectangle | |
win.add_overlay(face_rectangles); | |
win.add_overlay(dlib::render_face_detections(faces_landmarks)); | |
std::vector<dlib::matrix<float, 0, 1>> face_descriptors = face_recognition_dnn_model(face_images); | |
std::cout << argv[i] << std::endl; | |
for (size_t di = 0; di < face_descriptors.size(); di++) { | |
auto& face_descriptor = face_descriptors[di]; | |
std::cout << "face " << di << ": ["; | |
for (auto iterator = face_descriptor.begin(); iterator < face_descriptor.end(); iterator++) { | |
std::cout << *iterator << ", "; | |
} | |
std::cout << "]" << std::endl; | |
} | |
if (i < argc - 1) { | |
std::cout << "Press any button to continue..." << std::endl; | |
std::cin.get(); | |
} | |
} | |
win.wait_until_closed(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment