├── CMakeLists.txt ├── README.md ├── cpp_modules ├── alignment │ ├── cl_alignment.h │ ├── include │ │ ├── cln │ │ │ ├── CCNF_patch_expert.h │ │ │ ├── Face_utils.h │ │ │ ├── GazeEstimation.h │ │ │ ├── LandmarkCoreIncludes.h │ │ │ ├── LandmarkDetectionValidator.h │ │ │ ├── LandmarkDetectorFunc.h │ │ │ ├── LandmarkDetectorModel.h │ │ │ ├── LandmarkDetectorParameters.h │ │ │ ├── LandmarkDetectorUtils.h │ │ │ ├── PAW.h │ │ │ ├── PDM.h │ │ │ ├── Patch_experts.h │ │ │ ├── SVR_patch_expert.h │ │ │ ├── cln_alignment.h │ │ │ └── stdafx.h │ │ ├── es │ │ │ └── es_alignment.h │ │ ├── lbf │ │ │ ├── LBF.h │ │ │ ├── LBFRegressor.h │ │ │ ├── RandomForest.h │ │ │ ├── Tree.h │ │ │ ├── blas.h │ │ │ ├── blasp.h │ │ │ ├── lbf_alignment.h │ │ │ ├── linear.h │ │ │ └── tron.h │ │ └── utils.h │ └── src │ │ ├── cln │ │ ├── CCNF_patch_expert.cpp │ │ ├── Face_utils.cpp │ │ ├── GazeEstimation.cpp │ │ ├── LandmarkDetectionValidator.cpp │ │ ├── LandmarkDetectorFunc.cpp │ │ ├── LandmarkDetectorModel.cpp │ │ ├── LandmarkDetectorParameters.cpp │ │ ├── LandmarkDetectorUtils.cpp │ │ ├── PAW.cpp │ │ ├── PDM.cpp │ │ ├── Patch_experts.cpp │ │ ├── SVR_patch_expert.cpp │ │ ├── cln_alignment.cpp │ │ └── stdafx.cpp │ │ ├── es │ │ ├── Fern.cpp │ │ ├── FernCascade.cpp │ │ └── ShapeRegressor.cpp │ │ ├── lbf │ │ ├── LBF.cpp │ │ ├── LBFRegressor.cpp │ │ ├── RandomForest.cpp │ │ ├── Tree.cpp │ │ ├── daxpy.c │ │ ├── ddot.c │ │ ├── dnrm2.c │ │ ├── dscal.c │ │ ├── linear.cpp │ │ └── tron.cpp │ │ └── utils.cpp ├── camera │ ├── include │ │ ├── camera_model.h │ │ └── image_warping.h │ └── src │ │ └── image_warping.cpp ├── common │ └── cl_common.h ├── detection │ ├── cl_detector.h │ ├── include │ │ ├── mtcnn │ │ │ └── mtcnn.h │ │ └── seeta │ │ │ ├── classifier.h │ │ │ ├── classifier │ │ │ ├── lab_boosted_classifier.h │ │ │ ├── mlp.h │ │ │ └── surf_mlp.h │ │ │ ├── common.h │ │ │ ├── feat │ │ │ ├── lab_feature_map.h │ │ │ └── surf_feature_map.h │ │ │ ├── feature_map.h │ │ │ ├── io │ │ │ ├── lab_boost_model_reader.h │ │ │ └── surf_mlp_model_reader.h │ │ │ ├── model_reader.h │ │ │ ├── seeta_detector.h │ │ │ └── util │ │ │ ├── image_pyramid.h │ │ │ ├── math_func.h │ │ │ └── nms.h │ └── src │ │ ├── mtcnn │ │ └── mtcnn.cpp │ │ └── seeta │ │ ├── classifier │ │ ├── lab_boosted_classifier.cpp │ │ ├── mlp.cpp │ │ └── surf_mlp.cpp │ │ ├── feat │ │ ├── lab_feature_map.cpp │ │ └── surf_feature_map.cpp │ │ ├── io │ │ ├── lab_boost_model_reader.cpp │ │ └── surf_mlp_model_reader.cpp │ │ ├── seeta_detector.cpp │ │ └── util │ │ ├── image_pyramid.cpp │ │ └── nms.cpp ├── example │ ├── alignment_benchmark.cpp │ ├── all_in_one.cpp │ └── mtcnn_align_dataset.cpp ├── openpose │ ├── CMakeLists.txt │ ├── core │ │ ├── CMakeLists.txt │ │ ├── array.cpp │ │ ├── array.hpp │ │ ├── common.hpp │ │ ├── cvMatToOpInput.cpp │ │ ├── cvMatToOpInput.hpp │ │ ├── cvMatToOpOutput.cpp │ │ ├── cvMatToOpOutput.hpp │ │ ├── datum.cpp │ │ ├── datum.hpp │ │ ├── enumClasses.hpp │ │ ├── headers.hpp │ │ ├── keypointScaler.cpp │ │ ├── keypointScaler.hpp │ │ ├── macros.hpp │ │ ├── maximumBase.cpp │ │ ├── maximumBase.cu │ │ ├── maximumBase.hpp │ │ ├── maximumCaffe.cpp │ │ ├── maximumCaffe.hpp │ │ ├── net.hpp │ │ ├── netCaffe.cpp │ │ ├── netCaffe.hpp │ │ ├── nmsBase.cpp │ │ ├── nmsBase.cu │ │ ├── nmsBase.hpp │ │ ├── nmsCaffe.cpp │ │ ├── nmsCaffe.hpp │ │ ├── opOutputToCvMat.cpp │ │ ├── opOutputToCvMat.hpp │ │ ├── point.cpp │ │ ├── point.hpp │ │ ├── rectangle.cpp │ │ ├── rectangle.hpp │ │ ├── renderer.cpp │ │ ├── renderer.hpp │ │ ├── resizeAndMergeBase.cpp │ │ ├── resizeAndMergeBase.cu │ │ ├── resizeAndMergeBase.hpp │ │ ├── resizeAndMergeCaffe.cpp │ │ └── resizeAndMergeCaffe.hpp │ ├── face │ │ ├── CMakeLists.txt │ │ ├── faceExtractor.cpp │ │ ├── faceExtractor.hpp │ │ ├── faceParameters.hpp │ │ └── op_face.hpp │ └── utilities │ │ ├── CMakeLists.txt │ │ ├── check.hpp │ │ ├── cuda.cpp │ │ ├── cuda.hpp │ │ ├── cuda.hu │ │ ├── enumClasses.hpp │ │ ├── errorAndLog.cpp │ │ ├── errorAndLog.hpp │ │ ├── fastMath.hpp │ │ ├── fileSystem.cpp │ │ ├── fileSystem.hpp │ │ ├── flagsToOpenPose.cpp │ │ ├── flagsToOpenPose.hpp │ │ ├── headers.hpp │ │ ├── keypoint.cpp │ │ ├── keypoint.hpp │ │ ├── openCv.cpp │ │ ├── openCv.hpp │ │ ├── pointerContainer.hpp │ │ ├── profiler.cpp │ │ ├── profiler.hpp │ │ ├── render.hu │ │ ├── string.cpp │ │ └── string.hpp ├── recognition │ ├── cl_recognizer.h │ ├── include │ │ ├── net_caffe.h │ │ └── sphereface │ │ │ └── sphereface.h │ └── src │ │ ├── net_caffe.cpp │ │ └── sphereface │ │ └── sphereface.cpp └── tracking │ ├── CMakeLists.txt │ ├── tracker.cpp │ └── tracker.hpp ├── result ├── aligned.jpg ├── all.gif └── thumbnail.jpg └── trained_models └── detection ├── det1.caffemodel ├── det1.prototxt ├── det2.caffemodel ├── det2.prototxt ├── det3-half.caffemodel ├── det3-half.prototxt ├── det3.caffemodel └── det3.prototxt /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | project(cl_face C CXX) 3 | 4 | # Build options 5 | option(BUILD_EXAMPLES "Set to ON to build examples" ON) 6 | option(USE_OPENMP "Set to ON to build use openmp" ON) 7 | option(USE_SSE "Set to ON to build use SSE" ON) 8 | 9 | # Use C++11 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11") 11 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -gencode arch=compute_50,code=sm_50 12 | -gencode arch=compute_52,code=sm_52 13 | -gencode arch=compute_60,code=sm_60 14 | -gencode arch=compute_61,code=sm_61 15 | -gencode arch=compute_61,code=compute_61) 16 | 17 | if (USE_SSE) 18 | add_definitions(-DUSE_SSE) 19 | message(STATUS "Use SSE") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2") 21 | endif() 22 | 23 | # Use OpenMP 24 | if (USE_OPENMP) 25 | find_package(OpenMP QUIET) 26 | if (OPENMP_FOUND) 27 | message(STATUS "Use OpenMP") 28 | add_definitions(-DUSE_OPENMP) 29 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 30 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 31 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 32 | endif() 33 | endif() 34 | 35 | #Use OpenCV 36 | find_package(OpenCV) 37 | include_directories(${OpenCV_INCLUDE_DIRS}) 38 | 39 | #Use Boost 40 | find_package(Boost COMPONENTS system filesystem REQUIRED) 41 | include_directories(${Boost_INCLUDE_DIR}) 42 | link_directories(${Boost_LIBRARY_DIR}) 43 | 44 | #Use Caffe 45 | include_directories(/home/tpys/tools/caffe/distribute/include) 46 | link_directories(/home/tpys/tools/caffe/distribute/lib) 47 | 48 | #Use CUDA 49 | find_package(CUDA REQUIRED) 50 | include_directories(/usr/local/cuda-8.0/include) 51 | link_directories(/usr/local/cuda-8.0/lib64/) 52 | 53 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 54 | file(GLOB_RECURSE include_files ${CMAKE_CURRENT_SOURCE_DIR}/cpp_modules/*.h) 55 | foreach(file_path ${include_files}) 56 | get_filename_component(dir_path ${file_path} PATH) 57 | include_directories(${dir_path}) 58 | endforeach() 59 | 60 | file(GLOB_RECURSE detection_src cpp_modules/detection/src/*.cpp) 61 | file(GLOB_RECURSE alignment_src cpp_modules/alignment/src/*.cpp cpp_modules/alignment/src/*.c) 62 | file(GLOB_RECURSE recognition_src cpp_modules/recognition/src/*.cpp) 63 | 64 | # Build shared library 65 | set(BUILD_SHARED_LIBS ON) 66 | add_library(detection_lib ${detection_src}) 67 | add_library(alignment_lib ${alignment_src}) 68 | add_library(recognition_lib ${recognition_src}) 69 | 70 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_modules) 71 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cpp_modules/openpose) 72 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cpp_modules/tracking) 73 | 74 | 75 | # Build examples 76 | if (BUILD_EXAMPLES) 77 | message(STATUS "Build with examples.") 78 | list(APPEND face_app_libs detection_lib alignment_lib recognition_lib core face utilities caffe glog ${OpenCV_LIBS}) 79 | add_executable(alignment_benchmark 80 | cpp_modules/example/alignment_benchmark.cpp) 81 | target_link_libraries(alignment_benchmark ${face_app_libs}) 82 | 83 | add_executable(all_in_one cpp_modules/example/all_in_one.cpp 84 | cpp_modules/camera/src/image_warping.cpp) 85 | target_link_libraries(all_in_one ${face_app_libs}) 86 | 87 | add_executable(mtcnn_align_dataset 88 | cpp_modules/example/mtcnn_align_dataset.cpp) 89 | target_link_libraries(mtcnn_align_dataset ${face_app_libs} boost_filesystem) 90 | endif() 91 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/CCNF_patch_expert.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/CCNF_patch_expert.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/Face_utils.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (C) 2017, Carnegie Mellon University and University of Cambridge, 3 | // all rights reserved. 4 | // 5 | // ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY 6 | // 7 | // BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. 8 | // IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. 9 | // 10 | // License can be found in OpenFace-license.txt 11 | // 12 | // * Any publications arising from the use of this software, including but 13 | // not limited to academic journal and conference publications, technical 14 | // reports and manuals, must cite at least one of the following works: 15 | // 16 | // OpenFace: an open source facial behavior analysis toolkit 17 | // Tadas Baltru�aitis, Peter Robinson, and Louis-Philippe Morency 18 | // in IEEE Winter Conference on Applications of Computer Vision, 2016 19 | // 20 | // Rendering of Eyes for Eye-Shape Registration and Gaze Estimation 21 | // Erroll Wood, Tadas Baltru�aitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling 22 | // in IEEE International. Conference on Computer Vision (ICCV), 2015 23 | // 24 | // Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection 25 | // Tadas Baltru�aitis, Marwa Mahmoud, and Peter Robinson 26 | // in Facial Expression Recognition and Analysis Challenge, 27 | // IEEE International Conference on Automatic Face and Gesture Recognition, 2015 28 | // 29 | // Constrained Local Neural Fields for robust facial landmark detection in the wild. 30 | // Tadas Baltru�aitis, Peter Robinson, and Louis-Philippe Morency. 31 | // in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013. 32 | // 33 | /////////////////////////////////////////////////////////////////////////////// 34 | 35 | #ifndef __FACE_UTILS_h_ 36 | #define __FACE_UTILS_h_ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | namespace FaceAnalysis 43 | { 44 | //=========================================================================== 45 | // Defining a set of useful utility functions to be used within FaceAnalyser 46 | // Aligning a face to a common reference frame 47 | void AlignFace(cv::Mat& aligned_face, 48 | const cv::Mat& frame, 49 | const LandmarkDetector::CLNF& clnf_model, 50 | bool rigid = true, 51 | double scale = 0.6, 52 | int width = 96, 53 | int height = 112); 54 | 55 | 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/GazeEstimation.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/GazeEstimation.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/LandmarkCoreIncludes.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/LandmarkCoreIncludes.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/PAW.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/PAW.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/PDM.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/PDM.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/Patch_experts.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/Patch_experts.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/SVR_patch_expert.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/include/cln/SVR_patch_expert.h -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/cln_alignment.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-8-18. 3 | // 4 | 5 | #ifndef CL_FACE_OPENFACE_ALIGNMENT_H 6 | #define CL_FACE_OPENFACE_ALIGNMENT_H 7 | 8 | #include "LandmarkDetectorModel.h" 9 | 10 | #include "cl_alignment.h" 11 | #include "cl_common.h" 12 | 13 | namespace cln{ 14 | namespace fa{ 15 | 16 | class CLNAlignment:public cl::fa::Alignment{ 17 | public: 18 | CLNAlignment( 19 | bool use_face_template = false, 20 | bool multi_view = false, 21 | double sigma = 1.5, 22 | double reg_facetor = 25, 23 | double weight_factor = 0, 24 | double validation_boundary = -0.6, 25 | double cx = 0, 26 | double cy = 0, 27 | double fx = 0, 28 | double fy = 0); 29 | 30 | virtual ~CLNAlignment(){} 31 | 32 | 33 | bool detect(const cv::Mat& src, 34 | const std::vector& windows, 35 | std::vector& result); 36 | 37 | bool load_model(const std::vector& init_nets, 38 | const std::vector& predict_nets); 39 | 40 | void set_detector(cl::fd::Detector* detector) { clnf_model_->face_detector.reset(detector); } 41 | 42 | cv::Rect_ get_bbx() const { 43 | return clnf_model_->GetBoundingBox(); 44 | } 45 | 46 | 47 | private: 48 | inline bool is_valid_face(const cv::Vec6d& pose) const; 49 | void extract_rigid_points(cv::Mat_& source_points, cv::Mat_& destination_points); 50 | 51 | private: 52 | const double EulerThresh = 20; 53 | const double SimScale = 0.8; 54 | 55 | double fx_, fy_, cx_, cy_; 56 | LandmarkDetector::FaceModelParameters model_param_; 57 | shared_ptr< LandmarkDetector::CLNF> clnf_model_; 58 | 59 | DISABLE_COPY_AND_ASSIGN(CLNAlignment); 60 | }; 61 | } 62 | } 63 | 64 | 65 | 66 | 67 | #endif //CL_FACE_OPENFACE_ALIGNMENT_H 68 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/cln/stdafx.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (C) 2017, Carnegie Mellon University and University of Cambridge, 3 | // all rights reserved. 4 | // 5 | // ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY 6 | // 7 | // BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. 8 | // IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. 9 | // 10 | // License can be found in OpenFace-license.txt 11 | // 12 | 13 | // Precompiled headers stuff 14 | 15 | #ifndef __STDAFX_h_ 16 | #define __STDAFX_h_ 17 | 18 | // OpenCV includes 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // IplImage stuff 27 | #include 28 | #include 29 | 30 | // C++ stuff 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #define _USE_MATH_DEFINES 41 | #include 42 | 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/LBF.h: -------------------------------------------------------------------------------- 1 | // 2 | // LBF.h 3 | // myopencv 4 | // 5 | // Created by lequan on 1/24/15. 6 | // Copyright (c) 2015 lequan. All rights reserved. 7 | // 8 | 9 | #ifndef FACE_ALIGNMENT_LBF_H 10 | #define FACE_ALIGNMENT_LBF_H 11 | 12 | 13 | class Params{ 14 | public: 15 | Params(); 16 | double bagging_overlap; 17 | int max_numtrees; 18 | int max_depth; 19 | int landmark_num;// to be decided 20 | int initial_num; 21 | int max_numstage; 22 | double max_radio_radius[10]; 23 | int max_numfeats[10]; // number of pixel pairs 24 | int max_numthreshs; 25 | }; 26 | 27 | 28 | 29 | 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/RandomForest.h: -------------------------------------------------------------------------------- 1 | // 2 | // RandomForest.h 3 | // myopencv 4 | // 5 | // Created by lequan on 1/24/15. 6 | // Copyright (c) 2015 lequan. All rights reserved. 7 | // 8 | 9 | #ifndef __myopencv__RandomForest__ 10 | #define __myopencv__RandomForest__ 11 | 12 | #include "Tree.h" 13 | #include "LBF.h" 14 | 15 | class RandomForest{ 16 | public: 17 | std::vector > rfs_; 18 | int max_numtrees_; 19 | int num_landmark_; 20 | int max_depth_; 21 | int stages_; 22 | double overlap_ratio_; 23 | 24 | 25 | RandomForest(){ 26 | // max_numtrees_ = global_params.max_numtrees; 27 | // num_landmark_ = global_params.landmark_num; 28 | // max_depth_ = global_params.max_depth; 29 | // overlap_ratio_ = global_params.bagging_overlap; 30 | // 31 | // // resize the trees 32 | // rfs_.resize(num_landmark_); 33 | // for (int i=0;i >& images, 53 | const std::vector >& ground_truth_shapes, 54 | const std::vector >& current_shapes, 55 | const std::vector & bounding_boxs, 56 | const cv::Mat_& mean_shape, 57 | const std::vector >& shapes_residual, 58 | int stages 59 | ); 60 | void Read(std::ifstream& fin); 61 | void Write(std::ofstream& fout); 62 | 63 | private: 64 | Params params_; 65 | }; 66 | 67 | 68 | 69 | #endif /* defined(__myopencv__RandomForest__) */ 70 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/Tree.h: -------------------------------------------------------------------------------- 1 | // 2 | // Tree.h 3 | // myopencv 4 | // 5 | // Created by lequan on 1/23/15. 6 | // Copyright (c) 2015 lequan. All rights reserved. 7 | // 8 | 9 | #ifndef __myopencv__Tree__ 10 | #define __myopencv__Tree__ 11 | 12 | #include "LBF.h" 13 | #include "utils.h" 14 | 15 | class Node { 16 | public: 17 | //data 18 | bool issplit; 19 | int pnode; 20 | int depth; 21 | int cnodes[2]; 22 | bool isleafnode; 23 | double thresh; 24 | double feat[4]; 25 | std::vector ind_samples; 26 | 27 | //Constructors 28 | Node(){ 29 | ind_samples.clear(); 30 | issplit = 0; 31 | pnode = 0; 32 | depth = 0; 33 | cnodes[0] = 0; 34 | cnodes[1] = 0; 35 | isleafnode = 0; 36 | thresh = 0; 37 | feat[0] = 0; 38 | feat[1] = 0; 39 | feat[2] = 0; 40 | feat[3] = 0; 41 | } 42 | void Write(std::ofstream& fout){ 43 | fout << issplit<<" "<< pnode <<" "<> issplit >> pnode >> depth >> cnodes[0] >> cnodes[1] >> isleafnode 48 | >> thresh >> feat[0] >> feat[1] >> feat[2] >> feat[3]; 49 | } 50 | }; 51 | 52 | class Tree{ 53 | public: 54 | 55 | // id of the landmark 56 | int landmarkID_; 57 | // depth of the tree: 58 | int max_depth_; 59 | // number of maximum nodes: 60 | int max_numnodes_; 61 | //number of leaf nodes and nodes 62 | int num_leafnodes_; 63 | int num_nodes_; 64 | 65 | // sample pixel featurs' number, use when training RF 66 | int max_numfeats_; 67 | double max_radio_radius_; 68 | double overlap_ration_; 69 | 70 | // leafnodes id 71 | std::vector id_leafnodes_; 72 | // tree nodes 73 | std::vector nodes_; 74 | 75 | 76 | Tree(){ 77 | // overlap_ration_ = global_params.bagging_overlap; 78 | // max_depth_ = global_params.max_depth; 79 | // max_numnodes_ = pow(2, max_depth_)-1; 80 | // nodes_.resize(max_numnodes_); 81 | } 82 | 83 | Tree(const Params& params): params_(params) { 84 | overlap_ration_ = params.bagging_overlap; 85 | max_depth_ = params.max_depth; 86 | max_numnodes_ = pow(2, max_depth_)-1; 87 | nodes_.resize(max_numnodes_); 88 | } 89 | 90 | 91 | void Train(const std::vector >& images, 92 | const std::vector >& ground_truth_shapes, 93 | const std::vector >& current_shapes, 94 | const std::vector & bounding_boxs, 95 | const cv::Mat_& mean_shape, 96 | const std::vector >& regression_targets, 97 | const std::vector index, 98 | int stages, 99 | int landmarkID 100 | ); 101 | 102 | //Splite the node 103 | void Splitnode(const std::vector >& images, 104 | const std::vector >& ground_truth_shapes, 105 | const std::vector >& current_shapes, 106 | const std::vector & bounding_box, 107 | const cv::Mat_& mean_shape, 108 | const cv::Mat_& shapes_residual, 109 | const std::vector &ind_samples, 110 | // output 111 | double& thresh, 112 | double* feat, 113 | bool& isvaild, 114 | std::vector& lcind, 115 | std::vector& rcind 116 | ); 117 | 118 | //Predict 119 | void Predict(); 120 | 121 | // Read/ write 122 | void Read(std::ifstream& fin); 123 | void Write(std:: ofstream& fout); 124 | 125 | private: 126 | Params params_; 127 | 128 | }; 129 | 130 | 131 | 132 | 133 | 134 | #endif /* defined(__myopencv__Tree__) */ 135 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/blas.h: -------------------------------------------------------------------------------- 1 | /* blas.h -- C header file for BLAS Ver 1.0 */ 2 | /* Jesse Bennett March 23, 2000 */ 3 | 4 | /** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." 5 | 6 | - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ 7 | 8 | #ifndef BLAS_INCLUDE 9 | #define BLAS_INCLUDE 10 | 11 | /* Data types specific to BLAS implementation */ 12 | typedef struct { float r, i; } fcomplex; 13 | typedef struct { double r, i; } dcomplex; 14 | typedef int blasbool; 15 | 16 | #include "blasp.h" /* Prototypes for all BLAS functions */ 17 | 18 | #define FALSE 0 19 | #define TRUE 1 20 | 21 | /* Macro functions */ 22 | #define MIN(a,b) ((a) <= (b) ? (a) : (b)) 23 | #define MAX(a,b) ((a) >= (b) ? (a) : (b)) 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/lbf_alignment.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-25. 3 | // 4 | 5 | #ifndef CL_FACE_FPS3000_ALIGNMENT_H 6 | #define CL_FACE_FPS3000_ALIGNMENT_H 7 | 8 | 9 | #include "LBFRegressor.h" 10 | #include "LBF.h" 11 | 12 | namespace lbf{ 13 | namespace fa{ 14 | 15 | class LBFAlignment:public cl::fa::Alignment{ 16 | public: 17 | LBFAlignment(int iteration_num = 20):iteration_num_(iteration_num){} 18 | virtual ~LBFAlignment(){} 19 | 20 | bool detect(const cv::Mat& src, 21 | const std::vector& windows, 22 | std::vector& result){ 23 | 24 | cv::Mat img_gray; 25 | if (src.channels() != 1) 26 | cv::cvtColor(src, img_gray, cv::COLOR_BGR2GRAY); 27 | else 28 | img_gray = src; 29 | result.resize(windows.size()); 30 | 31 | // #pragma omp parallel for num_threads(CL_NUM_THREADS) 32 | for(size_t i = 0; i < windows.size(); ++i){ 33 | BoundingBox bbox(windows[i].bbox_.x, windows[i].bbox_.y, windows[i].bbox_.width, windows[i].bbox_.height); 34 | cv::Mat_ current_shape = regressor_->Predict(img_gray, bbox, iteration_num_); 35 | result[i].points_.resize(LandmarkNum); 36 | for(int j = 0; j < LandmarkNum; ++j ){ 37 | result[i].points_[j] = cv::Point2d(current_shape(j,0), current_shape(j,1)); 38 | } 39 | } 40 | } 41 | 42 | 43 | bool load_model(const std::vector& init_nets, 44 | const std::vector& predict_nets){ 45 | if(predict_nets.size() <= 0) { 46 | return false; 47 | } 48 | 49 | Params params_default; 50 | regressor_ = std::make_shared(params_default); 51 | regressor_->Load(init_nets[0], predict_nets[0]); 52 | return true; 53 | } 54 | 55 | private: 56 | const int LandmarkNum = 68; 57 | int iteration_num_; 58 | std::shared_ptr regressor_; 59 | DISABLE_COPY_AND_ASSIGN(LBFAlignment); 60 | }; 61 | } 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | #endif //CL_FACE_FPS3000_ALIGNMENT_H 70 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/linear.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBLINEAR_H 2 | #define _LIBLINEAR_H 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | struct feature_node 10 | { 11 | int index; 12 | double value; 13 | }; 14 | 15 | struct problem 16 | { 17 | int l, n; 18 | double *y; 19 | struct feature_node **x; 20 | double bias; /* < 0 if no bias term */ 21 | }; 22 | 23 | enum { L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL, L2R_L2LOSS_SVR = 11, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL }; /* solver_type */ 24 | 25 | struct parameter 26 | { 27 | int solver_type; 28 | 29 | /* these are for training only */ 30 | double eps; /* stopping criteria */ 31 | double C; 32 | int nr_weight; 33 | int *weight_label; 34 | double* weight; 35 | double p; 36 | }; 37 | 38 | struct model 39 | { 40 | struct parameter param; 41 | int nr_class; /* number of classes */ 42 | int nr_feature; 43 | double *w; 44 | int *label; /* label of each class */ 45 | double bias; 46 | }; 47 | 48 | struct model* train(const struct problem *prob, const struct parameter *param); 49 | void cross_validation(const struct problem *prob, const struct parameter *param, int nr_fold, double *target); 50 | 51 | double predict_values(const struct model *model_, const struct feature_node *x, double* dec_values); 52 | double predict(const struct model *model_, const struct feature_node *x); 53 | double predict_probability(const struct model *model_, const struct feature_node *x, double* prob_estimates); 54 | 55 | int save_model(const char *model_file_name, const struct model *model_); 56 | struct model *load_model(const char *model_file_name); 57 | /* add my own save and load model*/ 58 | int save_model_bin(std::ofstream& fout, const struct model *model_); 59 | struct model *load_model_bin(std::ifstream& fin); 60 | /*********************************/ 61 | 62 | int get_nr_feature(const struct model *model_); 63 | int get_nr_class(const struct model *model_); 64 | void get_labels(const struct model *model_, int* label); 65 | double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx); 66 | double get_decfun_bias(const struct model *model_, int label_idx); 67 | 68 | void free_model_content(struct model *model_ptr); 69 | void free_and_destroy_model(struct model **model_ptr_ptr); 70 | void destroy_param(struct parameter *param); 71 | 72 | const char *check_parameter(const struct problem *prob, const struct parameter *param); 73 | int check_probability_model(const struct model *model); 74 | int check_regression_model(const struct model *model); 75 | void set_print_string_function(void (*print_func) (const char*)); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif /* _LIBLINEAR_H */ 82 | 83 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/lbf/tron.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRON_H 2 | #define _TRON_H 3 | 4 | class function 5 | { 6 | public: 7 | virtual double fun(double *w) = 0 ; 8 | virtual void grad(double *w, double *g) = 0 ; 9 | virtual void Hv(double *s, double *Hs) = 0 ; 10 | 11 | virtual int get_nr_variable(void) = 0 ; 12 | virtual ~function(void){} 13 | }; 14 | 15 | class TRON 16 | { 17 | public: 18 | TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000); 19 | ~TRON(); 20 | 21 | void tron(double *w); 22 | void set_print_string(void (*i_print) (const char *buf)); 23 | 24 | private: 25 | int trcg(double delta, double *g, double *s, double *r); 26 | double norm_inf(int n, double *x); 27 | 28 | double eps; 29 | int max_iter; 30 | function *fun_obj; 31 | void info(const char *fmt,...); 32 | void (*tron_print_string)(const char *buf); 33 | }; 34 | #endif 35 | -------------------------------------------------------------------------------- /cpp_modules/alignment/include/utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-25. 3 | // 4 | 5 | #ifndef CL_FACE_UTILS_H 6 | #define CL_FACE_UTILS_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | class BoundingBox{ 28 | public: 29 | double start_x; 30 | double start_y; 31 | double width; 32 | double height; 33 | double centroid_x; 34 | double centroid_y; 35 | 36 | BoundingBox(){ 37 | start_x = 0; 38 | start_y = 0; 39 | width = 0; 40 | height = 0; 41 | centroid_x = 0; 42 | centroid_y = 0; 43 | }; 44 | 45 | BoundingBox(int _x, int _y, int _width, int _height){ 46 | start_x = _x; 47 | start_y = _y; 48 | width = _width; 49 | height = _height; 50 | centroid_x = (start_x + width/2); 51 | centroid_y = (start_y + height/2); 52 | }; 53 | }; 54 | 55 | cv::Mat_ GetMeanShape(const std::vector >& shapes, 56 | const std::vector& bounding_box); 57 | 58 | void GetShapeResidual(const std::vector >& ground_truth_shapes, 59 | const std::vector >& current_shapes, 60 | const std::vector& bounding_boxs, 61 | const cv::Mat_& mean_shape, 62 | std::vector >& shape_residuals); 63 | 64 | cv::Mat_ ProjectShape(const cv::Mat_& shape, const BoundingBox& bounding_box); 65 | cv::Mat_ ReProjectShape(const cv::Mat_& shape, const BoundingBox& bounding_box); 66 | void SimilarityTransform(const cv::Mat_& shape1, const cv::Mat_& shape2, 67 | cv::Mat_& rotation,double& scale); 68 | double calculate_covariance(const std::vector& v_1, 69 | const std::vector& v_2); 70 | void LoadData(std::string filepath, 71 | std::vector >& images, 72 | std::vector >& ground_truth_shapes, 73 | std::vector & bounding_box); 74 | void LoadDataAdjust(std::string filepath, 75 | std::vector >& images, 76 | std::vector >& ground_truth_shapes, 77 | std::vector & bounding_box); 78 | void LoadOpencvBbxData(std::string filepath, 79 | std::vector >& images, 80 | std::vector >& ground_truth_shapes, 81 | std::vector & bounding_boxs 82 | ); 83 | void LoadCofwTrainData(std::vector >& images, 84 | std::vector >& ground_truth_shapes, 85 | std::vector& bounding_boxs); 86 | void LoadCofwTestData(std::vector >& images, 87 | std::vector >& ground_truth_shapes, 88 | std::vector& bounding_boxs); 89 | 90 | BoundingBox CalculateBoundingBox(cv::Mat_& shape); 91 | cv::Mat_ LoadGroundTruthShape(std::string& filename); 92 | void adjustImage(cv::Mat_& img, 93 | cv::Mat_& ground_truth_shape, 94 | BoundingBox& bounding_box); 95 | 96 | void TrainModel(std::vector trainDataName); 97 | double TestModel(std::vector testDataName); 98 | int FaceDetectionAndAlignment(const char* inputname); 99 | void ReadGlobalParamFromFile(std::string path); 100 | double CalculateError(const cv::Mat_& ground_truth_shape, const cv::Mat_& predicted_shape); 101 | 102 | 103 | 104 | #endif //CL_FACE_UTILS_H 105 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/cln/GazeEstimation.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/src/cln/GazeEstimation.cpp -------------------------------------------------------------------------------- /cpp_modules/alignment/src/cln/LandmarkDetectorParameters.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (C) 2017, Carnegie Mellon University and University of Cambridge, 3 | // all rights reserved. 4 | // 5 | // ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY 6 | // 7 | // BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. 8 | // IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. 9 | // 10 | // License can be found in OpenFace-license.txt 11 | // 12 | // * Any publications arising from the use of this software, including but 13 | // not limited to academic journal and conference publications, technical 14 | // reports and manuals, must cite at least one of the following works: 15 | // 16 | // OpenFace: an open source facial behavior analysis toolkit 17 | // Tadas Baltru�aitis, Peter Robinson, and Louis-Philippe Morency 18 | // in IEEE Winter Conference on Applications of Computer Vision, 2016 19 | // 20 | // Rendering of Eyes for Eye-Shape Registration and Gaze Estimation 21 | // Erroll Wood, Tadas Baltru�aitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling 22 | // in IEEE International. Conference on Computer Vision (ICCV), 2015 23 | // 24 | // Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection 25 | // Tadas Baltru�aitis, Marwa Mahmoud, and Peter Robinson 26 | // in Facial Expression Recognition and Analysis Challenge, 27 | // IEEE International Conference on Automatic Face and Gesture Recognition, 2015 28 | // 29 | // Constrained Local Neural Fields for robust facial landmark detection in the wild. 30 | // Tadas Baltru�aitis, Peter Robinson, and Louis-Philippe Morency. 31 | // in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013. 32 | // 33 | /////////////////////////////////////////////////////////////////////////////// 34 | 35 | #include "stdafx.h" 36 | 37 | #include "LandmarkDetectorParameters.h" 38 | 39 | // Boost includes 40 | //#include 41 | //#include 42 | 43 | // System includes 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef CONFIG_DIR 49 | #define CONFIG_DIR "~" 50 | #endif 51 | 52 | using namespace std; 53 | 54 | using namespace LandmarkDetector; 55 | 56 | FaceModelParameters::FaceModelParameters() 57 | { 58 | // initialise the default values 59 | init(); 60 | } 61 | 62 | 63 | void FaceModelParameters::init() 64 | { 65 | 66 | // number of iterations that will be performed at each scale 67 | num_optimisation_iteration = 5; 68 | 69 | // using an external face checker based on SVM 70 | validate_detections = true; 71 | 72 | // Using hierarchical refinement by default (can be turned off) 73 | refine_hierarchical = true; 74 | 75 | // Refining parameters by default 76 | refine_parameters = true; 77 | 78 | window_sizes_small = vector(4); 79 | window_sizes_init = vector(4); 80 | 81 | // For fast tracking 82 | window_sizes_small[0] = 0; 83 | window_sizes_small[1] = 9; 84 | window_sizes_small[2] = 7; 85 | window_sizes_small[3] = 5; 86 | 87 | // Just for initialisation 88 | window_sizes_init.at(0) = 11; 89 | window_sizes_init.at(1) = 9; 90 | window_sizes_init.at(2) = 7; 91 | window_sizes_init.at(3) = 5; 92 | 93 | face_template_scale = 0.3; 94 | // Off by default (as it might lead to some slight inaccuracies in slowly moving faces) 95 | use_face_template = false; 96 | 97 | // For first frame use the initialisation 98 | window_sizes_current = window_sizes_init; 99 | 100 | model_location = ""; 101 | 102 | sigma = 1.5; 103 | reg_factor = 25; 104 | weight_factor = 0; // By default do not use NU-RLMS for videos as it does not work as well for them 105 | 106 | validation_boundary = -0.6; 107 | 108 | limit_pose = true; 109 | multi_view = false; 110 | 111 | reinit_video_every = 4; 112 | 113 | // Face detection 114 | face_detector_location = ""; 115 | quiet_mode = false; 116 | 117 | curr_face_detector = SEETA_DETECTOR; 118 | 119 | // The gaze tracking has to be explicitly initialised 120 | track_gaze = false; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/cln/PAW.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/src/cln/PAW.cpp -------------------------------------------------------------------------------- /cpp_modules/alignment/src/cln/SVR_patch_expert.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/cpp_modules/alignment/src/cln/SVR_patch_expert.cpp -------------------------------------------------------------------------------- /cpp_modules/alignment/src/cln/stdafx.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (C) 2017, Carnegie Mellon University and University of Cambridge, 3 | // all rights reserved. 4 | // 5 | // ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY 6 | // 7 | // BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. 8 | // IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. 9 | // 10 | // License can be found in OpenFace-license.txt 11 | // 12 | #include "stdafx.h" -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/LBF.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-25. 3 | // 4 | 5 | #include "LBF.h" 6 | 7 | 8 | Params::Params(): bagging_overlap(0.4), max_numtrees(10), max_depth(5), landmark_num(68), initial_num(5), max_numstage(7), 9 | max_radio_radius{0.4,0.3,0.2,0.15, 0.12, 0.10, 0.08, 0.06, 0.06,0.05}, 10 | max_numfeats{500, 500, 500, 300, 300, 200, 200,200,100,100}, max_numthreshs(500) { 11 | 12 | } -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/RandomForest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // RandomForest.cpp 3 | // myopencv 4 | // 5 | // Created by lequan on 1/24/15. 6 | // Copyright (c) 2015 lequan. All rights reserved. 7 | // 8 | 9 | #include "RandomForest.h" 10 | #include "RandomForest.h" 11 | using namespace std; 12 | using namespace cv; 13 | 14 | void RandomForest::Train( 15 | const vector >& images, 16 | const vector >& ground_truth_shapes, 17 | const vector >& current_shapes, 18 | const vector & bounding_boxs, 19 | const Mat_& mean_shape, 20 | const vector >& shapes_residual, 21 | int stages 22 | ){ 23 | stages_ = stages; 24 | #pragma omp parallel for 25 | for (int i=0;i index; 31 | index.reserve(Q+1); 32 | for (int j =0;j > stages_; 60 | fin >> max_numtrees_; 61 | fin >> num_landmark_; 62 | fin >> max_depth_; 63 | fin >> overlap_ratio_; 64 | for (int i=0; i< num_landmark_;i++){ 65 | for (int j = 0; j < max_numtrees_; j++){ 66 | rfs_[i][j].Read(fin); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/daxpy.c: -------------------------------------------------------------------------------- 1 | #include "blas.h" 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy, 8 | int *incy) 9 | { 10 | long int i, m, ix, iy, nn, iincx, iincy; 11 | register double ssa; 12 | 13 | /* constant times a vector plus a vector. 14 | uses unrolled loop for increments equal to one. 15 | jack dongarra, linpack, 3/11/78. 16 | modified 12/3/93, array(1) declarations changed to array(*) */ 17 | 18 | /* Dereference inputs */ 19 | nn = *n; 20 | ssa = *sa; 21 | iincx = *incx; 22 | iincy = *incy; 23 | 24 | if( nn > 0 && ssa != 0.0 ) 25 | { 26 | if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */ 27 | { 28 | m = nn-3; 29 | for (i = 0; i < m; i += 4) 30 | { 31 | sy[i] += ssa * sx[i]; 32 | sy[i+1] += ssa * sx[i+1]; 33 | sy[i+2] += ssa * sx[i+2]; 34 | sy[i+3] += ssa * sx[i+3]; 35 | } 36 | for ( ; i < nn; ++i) /* clean-up loop */ 37 | sy[i] += ssa * sx[i]; 38 | } 39 | else /* code for unequal increments or equal increments not equal to 1 */ 40 | { 41 | ix = iincx >= 0 ? 0 : (1 - nn) * iincx; 42 | iy = iincy >= 0 ? 0 : (1 - nn) * iincy; 43 | for (i = 0; i < nn; i++) 44 | { 45 | sy[iy] += ssa * sx[ix]; 46 | ix += iincx; 47 | iy += iincy; 48 | } 49 | } 50 | } 51 | 52 | return 0; 53 | } /* daxpy_ */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/ddot.c: -------------------------------------------------------------------------------- 1 | #include "blas.h" 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | double ddot_(int *n, double *sx, int *incx, double *sy, int *incy) 8 | { 9 | long int i, m, nn, iincx, iincy; 10 | double stemp; 11 | long int ix, iy; 12 | 13 | /* forms the dot product of two vectors. 14 | uses unrolled loops for increments equal to one. 15 | jack dongarra, linpack, 3/11/78. 16 | modified 12/3/93, array(1) declarations changed to array(*) */ 17 | 18 | /* Dereference inputs */ 19 | nn = *n; 20 | iincx = *incx; 21 | iincy = *incy; 22 | 23 | stemp = 0.0; 24 | if (nn > 0) 25 | { 26 | if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */ 27 | { 28 | m = nn-4; 29 | for (i = 0; i < m; i += 5) 30 | stemp += sx[i] * sy[i] + sx[i+1] * sy[i+1] + sx[i+2] * sy[i+2] + 31 | sx[i+3] * sy[i+3] + sx[i+4] * sy[i+4]; 32 | 33 | for ( ; i < nn; i++) /* clean-up loop */ 34 | stemp += sx[i] * sy[i]; 35 | } 36 | else /* code for unequal increments or equal increments not equal to 1 */ 37 | { 38 | ix = 0; 39 | iy = 0; 40 | if (iincx < 0) 41 | ix = (1 - nn) * iincx; 42 | if (iincy < 0) 43 | iy = (1 - nn) * iincy; 44 | for (i = 0; i < nn; i++) 45 | { 46 | stemp += sx[ix] * sy[iy]; 47 | ix += iincx; 48 | iy += iincy; 49 | } 50 | } 51 | } 52 | 53 | return stemp; 54 | } /* ddot_ */ 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/dnrm2.c: -------------------------------------------------------------------------------- 1 | #include /* Needed for fabs() and sqrt() */ 2 | #include "blas.h" 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | double dnrm2_(int *n, double *x, int *incx) 9 | { 10 | long int ix, nn, iincx; 11 | double norm, scale, absxi, ssq, temp; 12 | 13 | /* DNRM2 returns the euclidean norm of a vector via the function 14 | name, so that 15 | 16 | DNRM2 := sqrt( x'*x ) 17 | 18 | -- This version written on 25-October-1982. 19 | Modified on 14-October-1993 to inline the call to SLASSQ. 20 | Sven Hammarling, Nag Ltd. */ 21 | 22 | /* Dereference inputs */ 23 | nn = *n; 24 | iincx = *incx; 25 | 26 | if( nn > 0 && iincx > 0 ) 27 | { 28 | if (nn == 1) 29 | { 30 | norm = fabs(x[0]); 31 | } 32 | else 33 | { 34 | scale = 0.0; 35 | ssq = 1.0; 36 | 37 | /* The following loop is equivalent to this call to the LAPACK 38 | auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */ 39 | 40 | for (ix=(nn-1)*iincx; ix>=0; ix-=iincx) 41 | { 42 | if (x[ix] != 0.0) 43 | { 44 | absxi = fabs(x[ix]); 45 | if (scale < absxi) 46 | { 47 | temp = scale / absxi; 48 | ssq = ssq * (temp * temp) + 1.0; 49 | scale = absxi; 50 | } 51 | else 52 | { 53 | temp = absxi / scale; 54 | ssq += temp * temp; 55 | } 56 | } 57 | } 58 | norm = scale * sqrt(ssq); 59 | } 60 | } 61 | else 62 | norm = 0.0; 63 | 64 | return norm; 65 | 66 | } /* dnrm2_ */ 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | -------------------------------------------------------------------------------- /cpp_modules/alignment/src/lbf/dscal.c: -------------------------------------------------------------------------------- 1 | #include "blas.h" 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | int dscal_(int *n, double *sa, double *sx, int *incx) 8 | { 9 | long int i, m, nincx, nn, iincx; 10 | double ssa; 11 | 12 | /* scales a vector by a constant. 13 | uses unrolled loops for increment equal to 1. 14 | jack dongarra, linpack, 3/11/78. 15 | modified 3/93 to return if incx .le. 0. 16 | modified 12/3/93, array(1) declarations changed to array(*) */ 17 | 18 | /* Dereference inputs */ 19 | nn = *n; 20 | iincx = *incx; 21 | ssa = *sa; 22 | 23 | if (nn > 0 && iincx > 0) 24 | { 25 | if (iincx == 1) /* code for increment equal to 1 */ 26 | { 27 | m = nn-4; 28 | for (i = 0; i < m; i += 5) 29 | { 30 | sx[i] = ssa * sx[i]; 31 | sx[i+1] = ssa * sx[i+1]; 32 | sx[i+2] = ssa * sx[i+2]; 33 | sx[i+3] = ssa * sx[i+3]; 34 | sx[i+4] = ssa * sx[i+4]; 35 | } 36 | for ( ; i < nn; ++i) /* clean-up loop */ 37 | sx[i] = ssa * sx[i]; 38 | } 39 | else /* code for increment not equal to 1 */ 40 | { 41 | nincx = nn * iincx; 42 | for (i = 0; i < nincx; i += iincx) 43 | sx[i] = ssa * sx[i]; 44 | } 45 | } 46 | 47 | return 0; 48 | } /* dscal_ */ 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /cpp_modules/camera/include/camera_model.h: -------------------------------------------------------------------------------- 1 | #ifndef CL_FACE_UTILS_CAMERA_H 2 | #define CL_FACE_UTILS_CAMERA_H 3 | 4 | #include 5 | 6 | namespace cl { 7 | namespace camera { 8 | 9 | 10 | struct Camera{ 11 | Camera() {} 12 | virtual ~Camera(){} 13 | }; 14 | 15 | 16 | struct Fisheye: public Camera{ 17 | 18 | Fisheye(int pano_width = 1920, 19 | int input_width = 1296, 20 | int input_height = 992, 21 | int output_width = 960, 22 | int output_height = 960, 23 | int crop_width = 960, 24 | int crop_height = 960, 25 | float fu = 3.2709526837916417e+02, 26 | float fv = 3.3243670491075636e+02, 27 | float k1 = -7.7253987204226396e-02, 28 | float k2 = 2.0669709869175927e-02, 29 | float k3 = -8.3624290157720479e-03, 30 | float k4 = 2.6240108850240388e-03, 31 | float center_x = 6.4750000000000000e+02, 32 | float center_y = 4.9550000000000000e+02, 33 | float euler_x = 0, 34 | float euler_y = 0, 35 | float euler_z = 0, 36 | float tx = 0, 37 | float ty = 0, 38 | float tz = 0, 39 | float rotate_angle = -90):pano_width_(pano_width), 40 | input_width_(input_width), input_height_(input_height), 41 | output_width_(output_width), output_height_(output_height), 42 | crop_width_(crop_width), crop_height_(crop_height), 43 | fu_(fu), fv_(fv), k1_(k1), k2_(k2), k3_(k3), k4_(k4), 44 | center_x_(center_x), center_y_(center_y), 45 | euler_x_(euler_x), euler_y_(euler_y), euler_z_(euler_z), 46 | tx_(tx), ty_(ty), tz_(tz), 47 | rotate_angle_(rotate_angle){ 48 | } 49 | 50 | virtual ~Fisheye() {}; 51 | 52 | int pano_width_; 53 | int input_width_; 54 | int input_height_; 55 | int output_width_; 56 | int output_height_; 57 | int crop_width_; 58 | int crop_height_; 59 | 60 | float fu_; 61 | float fv_; 62 | float k1_; 63 | float k2_; 64 | float k3_; 65 | float k4_; 66 | 67 | float center_x_; 68 | float center_y_; 69 | 70 | float euler_x_; 71 | float euler_y_; 72 | float euler_z_; 73 | float tx_; 74 | float ty_; 75 | float tz_; 76 | 77 | float rotate_angle_ = -90; 78 | cv::Mat projection_ = cv::Mat(); 79 | }; 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | } 90 | } 91 | #endif -------------------------------------------------------------------------------- /cpp_modules/camera/include/image_warping.h: -------------------------------------------------------------------------------- 1 | #ifndef CL_FACE_UTILS_WRAPER_H 2 | #define CL_FACE_UTILS_WRAPER_H 3 | 4 | #include "camera_model.h" 5 | 6 | namespace cl { 7 | namespace camera { 8 | 9 | 10 | class Warping { 11 | public: 12 | virtual ~Warping() {} 13 | virtual void init(Camera *camera) = 0; 14 | virtual void init(Camera *camera, const cv::Rect &mask) = 0; 15 | virtual void undistort_image(const cv::Mat &src, cv::Mat &dst, int type = CV_8UC3) = 0; 16 | 17 | cv::Point2f get_center(cv::Size img_size); 18 | cv::Point2f get_rotation(cv::Point2f orig_pt, float angle); 19 | cv::Point2f circle_point2shperical_point(cv::Point2f sphere_pt, Camera *camera); 20 | }; 21 | 22 | 23 | class FisheyeWarping : public Warping { 24 | public: 25 | FisheyeWarping() {} 26 | void init(Camera *camera); 27 | void init(Camera *camera, const cv::Rect &mask); 28 | void undistort_image(const cv::Mat &src, cv::Mat &dst, int type = CV_8UC3); 29 | 30 | private: 31 | cv::Mat map_x_; 32 | cv::Mat map_y_; 33 | }; 34 | 35 | 36 | 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /cpp_modules/common/cl_common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cl on 17-8-16. 3 | // 4 | 5 | #ifndef CL_FACE_COMMON_H 6 | #define CL_FACE_COMMON_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef DISABLE_COPY_AND_ASSIGN 17 | #define DISABLE_COPY_AND_ASSIGN(classname) \ 18 | private: \ 19 | classname(const classname&) = delete; \ 20 | classname& operator=(const classname&) = delete 21 | #endif 22 | 23 | 24 | #define CL_NUM_THREADS 8 25 | #define USE_CAFFE 1 26 | 27 | namespace cl 28 | { 29 | template 30 | void split(const std::string &s, char delim, Out result) { 31 | std::stringstream ss; 32 | ss.str(s); 33 | std::string item; 34 | while (std::getline(ss, item, delim)) { 35 | *(result++) = item; 36 | } 37 | } 38 | 39 | static std::vector split(const std::string &s, char delim) { 40 | std::vector elems; 41 | split(s, delim, std::back_inserter(elems)); 42 | return elems; 43 | } 44 | 45 | struct FaceBox{ 46 | FaceBox(){} 47 | FaceBox(const cv::Rect& bbox, float score = 0):bbox_(bbox), score_(score) {} 48 | FaceBox(float x1, float y1, float x2, float y2, float score = 0) { 49 | bbox_.x = x1; 50 | bbox_.y = y1; 51 | bbox_.width = x2 - x1; 52 | bbox_.height = y2 - y1; 53 | score_ = score; 54 | } 55 | 56 | cv::Rect bbox_{0, 0, 0, 0}; 57 | double score_; 58 | }; 59 | 60 | struct FaceLandmark{ 61 | FaceLandmark():points_{}, scores_{} {} 62 | FaceLandmark(const std::vector& points):points_(points) {} 63 | FaceLandmark(const std::vector& points, 64 | const std::vector& scores):points_(points), scores_(scores) {} 65 | 66 | std::vector points_; 67 | std::vector scores_; 68 | }; 69 | 70 | 71 | struct FaceInfo 72 | { 73 | int identity_; 74 | }; 75 | 76 | 77 | const int TrainWidth = 182; 78 | const int TrainHeight = 182; 79 | const int TestWidth = 160; 80 | const int TestHeight = 160; 81 | 82 | } 83 | #endif //CL_FACE_COMMON_H 84 | -------------------------------------------------------------------------------- /cpp_modules/detection/cl_detector.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cl on 17-8-16. 3 | // 4 | 5 | #ifndef CL_FACE_DETECTIOR_H 6 | #define CL_FACE_DETECTIOR_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "cl_common.h" 13 | 14 | namespace cl { 15 | namespace fd{ 16 | class Detector{ 17 | public: 18 | Detector(){}; 19 | virtual ~Detector() {} 20 | virtual bool detect(const cv::Mat& src, std::vector& faces) = 0; 21 | virtual bool load_model(const std::vector& init_nets, 22 | const std::vector& predict_nets) = 0; 23 | 24 | 25 | cv::Rect get_biggest_rect(const std::vector& faces, int src_width, int src_height) { 26 | assert(faces.size() > 0); 27 | int idx = 0; 28 | float dist_max = 0; 29 | if (faces.size() == 1) { 30 | return faces[0].bbox_; 31 | } else { 32 | for(size_t i = 0; i < faces.size(); ++i) { 33 | float area = faces[i].bbox_.area(); 34 | cv::Point2f offset(faces[i].bbox_.x + faces[i].bbox_.width/2.0f - src_width/2.0f, 35 | faces[i].bbox_.y + faces[i].bbox_.height/2.0f - src_height/2.0f); 36 | float dist_squared = area - (offset.x * offset.x + offset.y * offset.y); 37 | if (dist_max < dist_squared){ 38 | dist_max = dist_squared; 39 | idx = i; 40 | } 41 | } 42 | return faces[idx].bbox_; 43 | } 44 | } 45 | 46 | 47 | 48 | private: 49 | DISABLE_COPY_AND_ASSIGN(Detector); 50 | 51 | }; 52 | } 53 | } 54 | 55 | 56 | 57 | #endif //CL_FACE_DETECTIOR_H 58 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/classifier.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_CLASSIFIER_H_ 33 | #define SEETA_FD_CLASSIFIER_H_ 34 | 35 | #include "common.h" 36 | #include "feature_map.h" 37 | 38 | namespace seeta { 39 | namespace fd { 40 | 41 | enum ClassifierType { 42 | LAB_Boosted_Classifier, 43 | SURF_MLP 44 | }; 45 | 46 | class Classifier { 47 | public: 48 | Classifier() {} 49 | virtual ~Classifier() {} 50 | 51 | virtual void SetFeatureMap(seeta::fd::FeatureMap* feat_map) = 0; 52 | virtual bool Classify(float* score = nullptr, float* outputs = nullptr) = 0; 53 | 54 | virtual seeta::fd::ClassifierType type() = 0; 55 | 56 | DISABLE_COPY_AND_ASSIGN(Classifier); 57 | }; 58 | 59 | } // namespace fd 60 | } // namespace seeta 61 | 62 | #endif // SEETA_FD_CLASSIFIER_H_ 63 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/classifier/lab_boosted_classifier.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_CLASSIFIER_LAB_BOOSTED_CLASSIFIER_H_ 33 | #define SEETA_FD_CLASSIFIER_LAB_BOOSTED_CLASSIFIER_H_ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "classifier.h" 41 | #include "feat/lab_feature_map.h" 42 | 43 | namespace seeta { 44 | namespace fd { 45 | 46 | /** 47 | * @class LABBaseClassifier 48 | * @brief Base classifier using LAB feature. 49 | */ 50 | class LABBaseClassifier { 51 | public: 52 | LABBaseClassifier() 53 | : num_bin_(255), thresh_(0.0f) { 54 | weights_.resize(num_bin_ + 1); 55 | } 56 | 57 | ~LABBaseClassifier() {} 58 | 59 | void SetWeights(const float* weights, int32_t num_bin); 60 | 61 | inline void SetThreshold(float thresh) { thresh_ = thresh; } 62 | 63 | inline int32_t num_bin() const { return num_bin_; } 64 | inline float weights(int32_t val) const { return weights_[val]; } 65 | inline float threshold() const { return thresh_; } 66 | 67 | private: 68 | int32_t num_bin_; 69 | 70 | std::vector weights_; 71 | float thresh_; 72 | }; 73 | 74 | /** 75 | * @class LABBoostedClassifier 76 | * @Brief A strong classifier constructed from base classifiers using LAB features. 77 | */ 78 | class LABBoostedClassifier : public Classifier { 79 | public: 80 | LABBoostedClassifier() : use_std_dev_(true) {} 81 | virtual ~LABBoostedClassifier() {} 82 | 83 | virtual bool Classify(float* score = nullptr, float* outputs = nullptr); 84 | 85 | inline virtual seeta::fd::ClassifierType type() { 86 | return seeta::fd::ClassifierType::LAB_Boosted_Classifier; 87 | } 88 | 89 | void AddFeature(int32_t x, int32_t y); 90 | void AddBaseClassifier(const float* weights, int32_t num_bin, float thresh); 91 | 92 | inline virtual void SetFeatureMap(seeta::fd::FeatureMap* featMap) { 93 | feat_map_ = dynamic_cast(featMap); 94 | } 95 | 96 | inline void SetUseStdDev(bool useStdDev) { use_std_dev_ = useStdDev; } 97 | 98 | private: 99 | static const int32_t kFeatGroupSize = 10; 100 | const float kStdDevThresh = 10.0f; 101 | 102 | std::vector feat_; 103 | std::vector > base_classifiers_; 104 | seeta::fd::LABFeatureMap* feat_map_; 105 | bool use_std_dev_; 106 | }; 107 | 108 | } // namespace fd 109 | } // namespace seeta 110 | 111 | #endif // SEETA_FD_CLASSIFIER_LAB_BOOSTED_CLASSIFIER_H_ 112 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/classifier/mlp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_CLASSIFIER_MLP_H_ 33 | #define SEETA_FD_CLASSIFIER_MLP_H_ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "util/math_func.h" 42 | 43 | namespace seeta { 44 | namespace fd { 45 | 46 | class MLPLayer { 47 | public: 48 | explicit MLPLayer(int32_t act_func_type = 1) 49 | : input_dim_(0), output_dim_(0), act_func_type_(act_func_type) {} 50 | ~MLPLayer() {} 51 | 52 | void Compute(const float* input, float* output); 53 | 54 | inline int32_t GetInputDim() const { return input_dim_; } 55 | inline int32_t GetOutputDim() const { return output_dim_; } 56 | 57 | inline void SetSize(int32_t inputDim, int32_t outputDim) { 58 | if (inputDim <= 0 || outputDim <= 0) { 59 | return; // @todo handle the errors!!! 60 | } 61 | input_dim_ = inputDim; 62 | output_dim_ = outputDim; 63 | weights_.resize(inputDim * outputDim); 64 | bias_.resize(outputDim); 65 | } 66 | 67 | inline void SetWeights(const float* weights, int32_t len) { 68 | if (weights == nullptr || len != input_dim_ * output_dim_) { 69 | return; // @todo handle the errors!!! 70 | } 71 | std::copy(weights, weights + input_dim_ * output_dim_, weights_.begin()); 72 | } 73 | 74 | inline void SetBias(const float* bias, int32_t len) { 75 | if (bias == nullptr || len != output_dim_) { 76 | return; // @todo handle the errors!!! 77 | } 78 | std::copy(bias, bias + output_dim_, bias_.begin()); 79 | } 80 | 81 | private: 82 | inline float Sigmoid(float x) { 83 | return 1.0f / (1.0f + std::exp(x)); 84 | } 85 | 86 | inline float ReLU(float x) { 87 | return (x > 0.0f ? x : 0.0f); 88 | } 89 | 90 | private: 91 | int32_t act_func_type_; 92 | int32_t input_dim_; 93 | int32_t output_dim_; 94 | std::vector weights_; 95 | std::vector bias_; 96 | }; 97 | 98 | 99 | class MLP { 100 | public: 101 | MLP() {} 102 | ~MLP() {} 103 | 104 | void Compute(const float* input, float* output); 105 | 106 | inline int32_t GetInputDim() const { 107 | return layers_[0]->GetInputDim(); 108 | } 109 | 110 | inline int32_t GetOutputDim() const { 111 | return layers_.back()->GetOutputDim(); 112 | } 113 | 114 | inline int32_t GetLayerNum() const { 115 | return static_cast(layers_.size()); 116 | } 117 | 118 | void AddLayer(int32_t inputDim, int32_t outputDim, const float* weights, 119 | const float* bias, bool is_output = false); 120 | 121 | private: 122 | std::vector > layers_; 123 | std::vector layer_buf_[2]; 124 | }; 125 | 126 | } // namespace fd 127 | } // namespace seeta 128 | 129 | #endif // SEETA_FD_CLASSIFIER_MLP_H_ 130 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/classifier/surf_mlp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_CLASSIFIER_SURF_MLP_H_ 33 | #define SEETA_FD_CLASSIFIER_SURF_MLP_H_ 34 | 35 | #include 36 | #include 37 | 38 | #include "classifier.h" 39 | #include "classifier/mlp.h" 40 | #include "feat/surf_feature_map.h" 41 | 42 | namespace seeta { 43 | namespace fd { 44 | 45 | class SURFMLP : public Classifier { 46 | public: 47 | SURFMLP() : Classifier(), model_(new seeta::fd::MLP()) {} 48 | virtual ~SURFMLP() {} 49 | 50 | virtual bool Classify(float* score = nullptr, float* outputs = nullptr); 51 | 52 | inline virtual void SetFeatureMap(seeta::fd::FeatureMap* feat_map) { 53 | feat_map_ = dynamic_cast(feat_map); 54 | } 55 | 56 | inline virtual seeta::fd::ClassifierType type() { 57 | return seeta::fd::ClassifierType::SURF_MLP; 58 | } 59 | 60 | void AddFeatureByID(int32_t feat_id); 61 | void AddLayer(int32_t input_dim, int32_t output_dim, const float* weights, 62 | const float* bias, bool is_output = false); 63 | 64 | inline void SetThreshold(float thresh) { thresh_ = thresh; } 65 | 66 | private: 67 | std::vector feat_id_; 68 | std::vector input_buf_; 69 | std::vector output_buf_; 70 | 71 | std::shared_ptr model_; 72 | float thresh_; 73 | seeta::fd::SURFFeatureMap* feat_map_; 74 | }; 75 | 76 | } // namespace fd 77 | } // namespace seeta 78 | 79 | #endif // SEETA_FD_CLASSIFIER_SURF_MLP_H_ 80 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_COMMON_H_ 33 | #define SEETA_COMMON_H_ 34 | 35 | #include 36 | 37 | #if defined _WIN32 38 | #ifdef SEETA_EXPORTS 39 | #define SEETA_API __declspec(dllexport) 40 | #else 41 | #define SEETA_API __declspec(dllimport) 42 | #endif 43 | 44 | #else 45 | #define SEETA_API 46 | #endif 47 | 48 | #define DISABLE_COPY_AND_ASSIGN(classname) \ 49 | private: \ 50 | classname(const classname&); \ 51 | classname& operator=(const classname&) 52 | 53 | #ifdef USE_OPENMP 54 | #include 55 | 56 | #define SEETA_NUM_THREADS 4 57 | #endif 58 | 59 | namespace seeta { 60 | 61 | typedef struct ImageData { 62 | ImageData() { 63 | data = nullptr; 64 | width = 0; 65 | height = 0; 66 | num_channels = 0; 67 | } 68 | 69 | ImageData(int32_t img_width, int32_t img_height, 70 | int32_t img_num_channels = 1) { 71 | data = nullptr; 72 | width = img_width; 73 | height = img_height; 74 | num_channels = img_num_channels; 75 | } 76 | 77 | uint8_t* data; 78 | int32_t width; 79 | int32_t height; 80 | int32_t num_channels; 81 | } ImageData; 82 | 83 | typedef struct Rect { 84 | int32_t x; 85 | int32_t y; 86 | int32_t width; 87 | int32_t height; 88 | } Rect; 89 | 90 | typedef struct FaceInfo { 91 | seeta::Rect bbox; 92 | 93 | double roll; 94 | double pitch; 95 | double yaw; 96 | 97 | double score; /**< Larger score should mean higher confidence. */ 98 | } FaceInfo; 99 | 100 | typedef struct { 101 | double x; 102 | double y; 103 | } FacialLandmark; 104 | } // namespace seeta 105 | 106 | #endif // SEETA_COMMON_H_ 107 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/feat/lab_feature_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_FEAT_LAB_FEATURE_MAP_H_ 33 | #define SEETA_FD_FEAT_LAB_FEATURE_MAP_H_ 34 | 35 | #include 36 | 37 | #include "feature_map.h" 38 | 39 | namespace seeta { 40 | namespace fd { 41 | 42 | /** @struct LABFeature 43 | * @brief Locally Assembled Binary (LAB) feature. 44 | * 45 | * It is parameterized by the coordinates of top left corner. 46 | */ 47 | typedef struct LABFeature { 48 | int32_t x; 49 | int32_t y; 50 | } LABFeature; 51 | 52 | class LABFeatureMap : public seeta::fd::FeatureMap { 53 | public: 54 | LABFeatureMap() : rect_width_(3), rect_height_(3), num_rect_(3) {} 55 | virtual ~LABFeatureMap() {} 56 | 57 | virtual void Compute(const uint8_t* input, int32_t width, int32_t height); 58 | 59 | inline uint8_t GetFeatureVal(int32_t offset_x, int32_t offset_y) const { 60 | return feat_map_[(roi_.y + offset_y) * width_ + roi_.x + offset_x]; 61 | } 62 | 63 | float GetStdDev() const; 64 | 65 | private: 66 | void Reshape(int32_t width, int32_t height); 67 | void ComputeIntegralImages(const uint8_t* input); 68 | void ComputeRectSum(); 69 | void ComputeFeatureMap(); 70 | 71 | template 72 | inline void Integral(Int32Type* data) { 73 | const Int32Type* src = data; 74 | Int32Type* dest = data; 75 | const Int32Type* dest_above = dest; 76 | 77 | *dest = *(src++); 78 | for (int32_t c = 1; c < width_; c++, src++, dest++) 79 | *(dest + 1) = (*dest) + (*src); 80 | dest++; 81 | for (int32_t r = 1; r < height_; r++) { 82 | for (int32_t c = 0, s = 0; c < width_; c++, src++, dest++, dest_above++) { 83 | s += (*src); 84 | *dest = *dest_above + s; 85 | } 86 | } 87 | } 88 | 89 | const int32_t rect_width_; 90 | const int32_t rect_height_; 91 | const int32_t num_rect_; 92 | 93 | std::vector feat_map_; 94 | std::vector rect_sum_; 95 | std::vector int_img_; 96 | std::vector square_int_img_; 97 | }; 98 | 99 | } // namespace fd 100 | } // namespace seeta 101 | 102 | #endif // SEETA_FD_FEAT_LAB_FEATURE_MAP_H_ 103 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/feature_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_FEATURE_MAP_H_ 33 | #define SEETA_FD_FEATURE_MAP_H_ 34 | 35 | #include "common.h" 36 | 37 | namespace seeta { 38 | namespace fd { 39 | 40 | class FeatureMap { 41 | public: 42 | FeatureMap() 43 | : width_(0), height_(0) { 44 | roi_.x = 0; 45 | roi_.y = 0; 46 | roi_.width = 0; 47 | roi_.height = 0; 48 | } 49 | 50 | virtual ~FeatureMap() {} 51 | 52 | virtual void Compute(const uint8_t* input, int32_t width, int32_t height) = 0; 53 | 54 | inline virtual void SetROI(const seeta::Rect & roi) { 55 | roi_ = roi; 56 | } 57 | 58 | protected: 59 | int32_t width_; 60 | int32_t height_; 61 | 62 | seeta::Rect roi_; 63 | }; 64 | 65 | } // namespace fd 66 | } // namespace seeta 67 | 68 | #endif // SEETA_FD_FEATURE_MAP_H_ 69 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/io/lab_boost_model_reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_IO_LAB_BOOST_MODEL_READER_H_ 33 | #define SEETA_FD_IO_LAB_BOOST_MODEL_READER_H_ 34 | 35 | #include 36 | #include 37 | 38 | #include "model_reader.h" 39 | #include "classifier/lab_boosted_classifier.h" 40 | 41 | namespace seeta { 42 | namespace fd { 43 | 44 | class LABBoostModelReader : public ModelReader { 45 | public: 46 | LABBoostModelReader() : ModelReader() {} 47 | virtual ~LABBoostModelReader() {} 48 | 49 | virtual bool Read(std::istream* input, seeta::fd::Classifier* model); 50 | 51 | private: 52 | bool ReadFeatureParam(std::istream* input, 53 | seeta::fd::LABBoostedClassifier* model); 54 | bool ReadBaseClassifierParam(std::istream* input, 55 | seeta::fd::LABBoostedClassifier* model); 56 | 57 | int32_t num_bin_; 58 | int32_t num_base_classifer_; 59 | }; 60 | 61 | } // namespace fd 62 | } // namespace seeta 63 | 64 | #endif // SEETA_FD_IO_LAB_BOOST_MODEL_READER_H_ 65 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/io/surf_mlp_model_reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_IO_SURF_MLP_MODEL_READER_H_ 33 | #define SEETA_FD_IO_SURF_MLP_MODEL_READER_H_ 34 | 35 | #include 36 | #include 37 | 38 | #include "model_reader.h" 39 | 40 | namespace seeta { 41 | namespace fd { 42 | 43 | class SURFMLPModelReader : public ModelReader { 44 | public: 45 | SURFMLPModelReader() {} 46 | virtual ~SURFMLPModelReader() {} 47 | 48 | virtual bool Read(std::istream* input, seeta::fd::Classifier* model); 49 | 50 | private: 51 | std::vector feat_id_buf_; 52 | std::vector weights_buf_; 53 | std::vector bias_buf_; 54 | }; 55 | 56 | } // namespace fd 57 | } // namespace seeta 58 | 59 | #endif // SEETA_FD_IO_SURF_MLP_MODEL_READER_H_ 60 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/model_reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_MODEL_READER_H_ 33 | #define SEETA_FD_MODEL_READER_H_ 34 | 35 | #include 36 | 37 | #include "classifier.h" 38 | 39 | namespace seeta { 40 | namespace fd { 41 | 42 | class ModelReader { 43 | public: 44 | ModelReader() {} 45 | virtual ~ModelReader() {} 46 | 47 | virtual bool Read(std::istream* input, seeta::fd::Classifier* model) = 0; 48 | 49 | DISABLE_COPY_AND_ASSIGN(ModelReader); 50 | }; 51 | 52 | } // namespace fd 53 | } // namespace seeta 54 | 55 | #endif // SEETA_FD_MODEL_READER_H_ 56 | -------------------------------------------------------------------------------- /cpp_modules/detection/include/seeta/util/nms.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #ifndef SEETA_FD_UTIL_NMS_H_ 33 | #define SEETA_FD_UTIL_NMS_H_ 34 | 35 | #include 36 | #include "cl_common.h" 37 | 38 | namespace seeta { 39 | namespace fd { 40 | 41 | void NonMaximumSuppression(std::vector* bboxes, 42 | std::vector* bboxes_nms, float iou_thresh = 0.8f); 43 | 44 | } // namespace fd 45 | } // namespace seeta 46 | 47 | #endif // SEETA_FD_UTIL_NMS_H_ 48 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/classifier/lab_boosted_classifier.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "classifier/lab_boosted_classifier.h" 33 | 34 | #include 35 | #include 36 | 37 | namespace seeta { 38 | namespace fd { 39 | 40 | void LABBaseClassifier::SetWeights(const float* weights, int32_t num_bin) { 41 | weights_.resize(num_bin + 1); 42 | num_bin_ = num_bin; 43 | std::copy(weights, weights + num_bin_ + 1, weights_.begin()); 44 | } 45 | 46 | bool LABBoostedClassifier::Classify(float* score, float* outputs) { 47 | bool isPos = true; 48 | float s = 0.0f; 49 | 50 | for (size_t i = 0; isPos && i < base_classifiers_.size();) { 51 | for (int32_t j = 0; j < kFeatGroupSize; j++, i++) { 52 | uint8_t featVal = feat_map_->GetFeatureVal(feat_[i].x, feat_[i].y); 53 | s += base_classifiers_[i]->weights(featVal); 54 | } 55 | if (s < base_classifiers_[i - 1]->threshold()) 56 | isPos = false; 57 | } 58 | isPos = isPos && ((!use_std_dev_) || feat_map_->GetStdDev() > kStdDevThresh); 59 | 60 | if (score != nullptr) 61 | *score = s; 62 | if (outputs != nullptr) 63 | *outputs = s; 64 | 65 | return isPos; 66 | } 67 | 68 | void LABBoostedClassifier::AddFeature(int32_t x, int32_t y) { 69 | LABFeature feat; 70 | feat.x = x; 71 | feat.y = y; 72 | feat_.push_back(feat); 73 | } 74 | 75 | void LABBoostedClassifier::AddBaseClassifier(const float* weights, 76 | int32_t num_bin, float thresh) { 77 | std::shared_ptr classifier(new LABBaseClassifier()); 78 | classifier->SetWeights(weights, num_bin); 79 | classifier->SetThreshold(thresh); 80 | base_classifiers_.push_back(classifier); 81 | } 82 | 83 | } // namespace fd 84 | } // namespace seeta 85 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/classifier/mlp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "classifier/mlp.h" 33 | 34 | #include "common.h" 35 | 36 | namespace seeta { 37 | namespace fd { 38 | 39 | void MLPLayer::Compute(const float* input, float* output) { 40 | #pragma omp parallel num_threads(SEETA_NUM_THREADS) 41 | { 42 | #pragma omp for nowait 43 | for (int32_t i = 0; i < output_dim_; i++) { 44 | output[i] = seeta::fd::MathFunction::VectorInnerProduct(input, 45 | weights_.data() + i * input_dim_, input_dim_) + bias_[i]; 46 | output[i] = (act_func_type_ == 1 ? ReLU(output[i]) : Sigmoid(-output[i])); 47 | } 48 | } 49 | } 50 | 51 | void MLP::Compute(const float* input, float* output) { 52 | layer_buf_[0].resize(layers_[0]->GetOutputDim()); 53 | layers_[0]->Compute(input, layer_buf_[0].data()); 54 | 55 | size_t i; /**< layer index */ 56 | for (i = 1; i < layers_.size() - 1; i++) { 57 | layer_buf_[i % 2].resize(layers_[i]->GetOutputDim()); 58 | layers_[i]->Compute(layer_buf_[(i + 1) % 2].data(), layer_buf_[i % 2].data()); 59 | } 60 | layers_.back()->Compute(layer_buf_[(i + 1) % 2].data(), output); 61 | } 62 | 63 | void MLP::AddLayer(int32_t inputDim, int32_t outputDim, const float* weights, 64 | const float* bias, bool is_output) { 65 | if (layers_.size() > 0 && inputDim != layers_.back()->GetOutputDim()) 66 | return; // @todo handle the errors!!! 67 | 68 | std::shared_ptr layer(new seeta::fd::MLPLayer(is_output ? 0 : 1)); 69 | layer->SetSize(inputDim, outputDim); 70 | layer->SetWeights(weights, inputDim * outputDim); 71 | layer->SetBias(bias, outputDim); 72 | layers_.push_back(layer); 73 | } 74 | 75 | } // namespace fd 76 | } // namespace seeta 77 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/classifier/surf_mlp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "classifier/surf_mlp.h" 33 | 34 | #include 35 | 36 | namespace seeta { 37 | namespace fd { 38 | 39 | bool SURFMLP::Classify(float* score, float* outputs) { 40 | float* dest = input_buf_.data(); 41 | for (size_t i = 0; i < feat_id_.size(); i++) { 42 | feat_map_->GetFeatureVector(feat_id_[i] - 1, dest); 43 | dest += feat_map_->GetFeatureVectorDim(feat_id_[i]); 44 | } 45 | output_buf_.resize(model_->GetOutputDim()); 46 | model_->Compute(input_buf_.data(), output_buf_.data()); 47 | 48 | if (score != nullptr) 49 | *score = output_buf_[0]; 50 | if (outputs != nullptr) { 51 | std::memcpy(outputs, output_buf_.data(), 52 | model_->GetOutputDim() * sizeof(float)); 53 | } 54 | 55 | return (output_buf_[0] > thresh_); 56 | } 57 | 58 | void SURFMLP::AddFeatureByID(int32_t feat_id) { 59 | feat_id_.push_back(feat_id); 60 | } 61 | 62 | void SURFMLP::AddLayer(int32_t input_dim, int32_t output_dim, 63 | const float* weights, const float* bias, bool is_output) { 64 | if (model_->GetLayerNum() == 0) 65 | input_buf_.resize(input_dim); 66 | model_->AddLayer(input_dim, output_dim, weights, bias, is_output); 67 | } 68 | 69 | } // namespace fd 70 | } // namespace seeta 71 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/io/lab_boost_model_reader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "io/lab_boost_model_reader.h" 33 | 34 | #include 35 | 36 | namespace seeta { 37 | namespace fd { 38 | 39 | bool LABBoostModelReader::Read(std::istream* input, 40 | seeta::fd::Classifier* model) { 41 | bool is_read; 42 | seeta::fd::LABBoostedClassifier* lab_boosted_classifier = 43 | dynamic_cast(model); 44 | 45 | input->read(reinterpret_cast(&num_base_classifer_), sizeof(int32_t)); 46 | input->read(reinterpret_cast(&num_bin_), sizeof(int32_t)); 47 | 48 | is_read = (!input->fail()) && num_base_classifer_ > 0 && num_bin_ > 0 && 49 | ReadFeatureParam(input, lab_boosted_classifier) && 50 | ReadBaseClassifierParam(input, lab_boosted_classifier); 51 | 52 | return is_read; 53 | } 54 | 55 | bool LABBoostModelReader::ReadFeatureParam(std::istream* input, 56 | seeta::fd::LABBoostedClassifier* model) { 57 | int32_t x; 58 | int32_t y; 59 | for (int32_t i = 0; i < num_base_classifer_; i++) { 60 | input->read(reinterpret_cast(&x), sizeof(int32_t)); 61 | input->read(reinterpret_cast(&y), sizeof(int32_t)); 62 | model->AddFeature(x, y); 63 | } 64 | 65 | return !input->fail(); 66 | } 67 | 68 | bool LABBoostModelReader::ReadBaseClassifierParam(std::istream* input, 69 | seeta::fd::LABBoostedClassifier* model) { 70 | std::vector thresh; 71 | thresh.resize(num_base_classifer_); 72 | input->read(reinterpret_cast(thresh.data()), 73 | sizeof(float)* num_base_classifer_); 74 | 75 | int32_t weight_len = sizeof(float)* (num_bin_ + 1); 76 | std::vector weights; 77 | weights.resize(num_bin_ + 1); 78 | for (int32_t i = 0; i < num_base_classifer_; i++) { 79 | input->read(reinterpret_cast(weights.data()), weight_len); 80 | model->AddBaseClassifier(weights.data(), num_bin_, thresh[i]); 81 | } 82 | 83 | return !input->fail(); 84 | } 85 | 86 | } // namespace fd 87 | } // namespace seeta 88 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/io/surf_mlp_model_reader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "io/surf_mlp_model_reader.h" 33 | 34 | #include 35 | 36 | #include "classifier/surf_mlp.h" 37 | 38 | namespace seeta { 39 | namespace fd { 40 | 41 | bool SURFMLPModelReader::Read(std::istream* input, 42 | seeta::fd::Classifier* model) { 43 | bool is_read = false; 44 | seeta::fd::SURFMLP* surf_mlp = dynamic_cast(model); 45 | int32_t num_layer; 46 | int32_t num_feat; 47 | int32_t input_dim; 48 | int32_t output_dim; 49 | float thresh; 50 | 51 | input->read(reinterpret_cast(&num_layer), sizeof(int32_t)); 52 | if (num_layer <= 0) { 53 | is_read = false; // @todo handle the errors and the following ones!!! 54 | } 55 | input->read(reinterpret_cast(&num_feat), sizeof(int32_t)); 56 | if (num_feat <= 0) { 57 | is_read = false; 58 | } 59 | 60 | feat_id_buf_.resize(num_feat); 61 | input->read(reinterpret_cast(feat_id_buf_.data()), 62 | sizeof(int32_t) * num_feat); 63 | for (int32_t i = 0; i < num_feat; i++) 64 | surf_mlp->AddFeatureByID(feat_id_buf_[i]); 65 | 66 | input->read(reinterpret_cast(&thresh), sizeof(float)); 67 | surf_mlp->SetThreshold(thresh); 68 | input->read(reinterpret_cast(&input_dim), sizeof(int32_t)); 69 | if (input_dim <= 0) { 70 | is_read = false; 71 | } 72 | 73 | for (int32_t i = 1; i < num_layer; i++) { 74 | input->read(reinterpret_cast(&output_dim), sizeof(int32_t)); 75 | if (output_dim <= 0) { 76 | is_read = false; 77 | } 78 | 79 | int32_t len = input_dim * output_dim; 80 | weights_buf_.resize(len); 81 | input->read(reinterpret_cast(weights_buf_.data()), 82 | sizeof(float) * len); 83 | 84 | bias_buf_.resize(output_dim); 85 | input->read(reinterpret_cast(bias_buf_.data()), 86 | sizeof(float) * output_dim); 87 | 88 | if (i < num_layer - 1) { 89 | surf_mlp->AddLayer(input_dim, output_dim, weights_buf_.data(), 90 | bias_buf_.data()); 91 | } else { 92 | surf_mlp->AddLayer(input_dim, output_dim, weights_buf_.data(), 93 | bias_buf_.data(), true); 94 | } 95 | input_dim = output_dim; 96 | } 97 | 98 | is_read = !input->fail(); 99 | 100 | return is_read; 101 | } 102 | 103 | } // namespace fd 104 | } // namespace seeta 105 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/util/image_pyramid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | 32 | #include "util/image_pyramid.h" 33 | 34 | namespace seeta { 35 | namespace fd { 36 | 37 | const seeta::ImageData* ImagePyramid::GetNextScaleImage(float* scale_factor) { 38 | if (scale_factor_ >= min_scale_) { 39 | if (scale_factor != nullptr) 40 | *scale_factor = scale_factor_; 41 | 42 | width_scaled_ = static_cast(width1x_ * scale_factor_); 43 | height_scaled_ = static_cast(height1x_ * scale_factor_); 44 | 45 | seeta::ImageData src_img(width1x_, height1x_); 46 | seeta::ImageData dest_img(width_scaled_, height_scaled_); 47 | src_img.data = buf_img_; 48 | dest_img.data = buf_img_scaled_; 49 | seeta::fd::ResizeImage(src_img, &dest_img); 50 | scale_factor_ *= scale_step_; 51 | 52 | img_scaled_.data = buf_img_scaled_; 53 | img_scaled_.width = width_scaled_; 54 | img_scaled_.height = height_scaled_; 55 | return &img_scaled_; 56 | } else { 57 | return nullptr; 58 | } 59 | } 60 | 61 | void ImagePyramid::SetImage1x(const uint8_t* img_data, int32_t width, 62 | int32_t height) { 63 | if (width > buf_img_width_ || height > buf_img_height_) { 64 | delete[] buf_img_; 65 | 66 | buf_img_width_ = width; 67 | buf_img_height_ = height; 68 | buf_img_ = new uint8_t[width * height]; 69 | } 70 | 71 | width1x_ = width; 72 | height1x_ = height; 73 | std::memcpy(buf_img_, img_data, width * height * sizeof(uint8_t)); 74 | scale_factor_ = max_scale_; 75 | UpdateBufScaled(); 76 | } 77 | 78 | void ImagePyramid::UpdateBufScaled() { 79 | if (width1x_ == 0 || height1x_ == 0) 80 | return; 81 | 82 | int32_t max_width = static_cast(width1x_ * max_scale_ + 0.5); 83 | int32_t max_height = static_cast(height1x_ * max_scale_ + 0.5); 84 | 85 | if (max_width > buf_scaled_width_ || max_height > buf_scaled_height_) { 86 | delete[] buf_img_scaled_; 87 | 88 | buf_scaled_width_ = max_width; 89 | buf_scaled_height_ = max_height; 90 | buf_img_scaled_ = new uint8_t[max_width * max_height]; 91 | 92 | img_scaled_.data = nullptr; 93 | img_scaled_.width = 0; 94 | img_scaled_.height = 0; 95 | } 96 | } 97 | 98 | } // namespace fd 99 | } // namespace seeta 100 | -------------------------------------------------------------------------------- /cpp_modules/detection/src/seeta/util/nms.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * This file is part of the open-source SeetaFace engine, which includes three modules: 4 | * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification. 5 | * 6 | * This file is part of the SeetaFace Detection module, containing codes implementing the 7 | * face detection method described in the following paper: 8 | * 9 | * 10 | * Funnel-structured cascade for multi-view face detection with alignment awareness, 11 | * Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen. 12 | * In Neurocomputing (under review) 13 | * 14 | * 15 | * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group, 16 | * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China. 17 | * 18 | * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan) 19 | * 20 | * As an open-source face recognition engine: you can redistribute SeetaFace source codes 21 | * and/or modify it under the terms of the BSD 2-Clause License. 22 | * 23 | * You should have received a copy of the BSD 2-Clause License along with the software. 24 | * If not, see < https://opensource.org/licenses/BSD-2-Clause>. 25 | * 26 | * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems. 27 | * 28 | * Note: the above information must be kept whenever or wherever the codes are used. 29 | * 30 | */ 31 | #include 32 | #include "util/nms.h" 33 | 34 | namespace seeta { 35 | namespace fd { 36 | 37 | bool CompareBBox(const cl::FaceBox & a, const cl::FaceBox & b) { 38 | return a.score_ > b.score_; 39 | } 40 | 41 | void NonMaximumSuppression(std::vector* bboxes, 42 | std::vector* bboxes_nms, float iou_thresh) { 43 | bboxes_nms->clear(); 44 | std::sort(bboxes->begin(), bboxes->end(), CompareBBox); 45 | 46 | int32_t select_idx = 0; 47 | int32_t num_bbox = static_cast(bboxes->size()); 48 | std::vector mask_merged(num_bbox, 0); 49 | bool all_merged = false; 50 | 51 | while (!all_merged) { 52 | while (select_idx < num_bbox && mask_merged[select_idx] == 1) 53 | select_idx++; 54 | if (select_idx == num_bbox) { 55 | all_merged = true; 56 | continue; 57 | } 58 | 59 | bboxes_nms->push_back((*bboxes)[select_idx]); 60 | mask_merged[select_idx] = 1; 61 | 62 | cv::Rect select_bbox = (*bboxes)[select_idx].bbox_; 63 | float area1 = static_cast(select_bbox.width * select_bbox.height); 64 | float x1 = static_cast(select_bbox.x); 65 | float y1 = static_cast(select_bbox.y); 66 | float x2 = static_cast(select_bbox.x + select_bbox.width - 1); 67 | float y2 = static_cast(select_bbox.y + select_bbox.height - 1); 68 | 69 | select_idx++; 70 | for (int32_t i = select_idx; i < num_bbox; i++) { 71 | if (mask_merged[i] == 1) 72 | continue; 73 | 74 | cv::Rect & bbox_i = (*bboxes)[i].bbox_; 75 | float x = std::max(x1, static_cast(bbox_i.x)); 76 | float y = std::max(y1, static_cast(bbox_i.y)); 77 | float w = std::min(x2, static_cast(bbox_i.x + bbox_i.width - 1)) - x + 1; 78 | float h = std::min(y2, static_cast(bbox_i.y + bbox_i.height - 1)) - y + 1; 79 | if (w <= 0 || h <= 0) 80 | continue; 81 | 82 | float area2 = static_cast(bbox_i.width * bbox_i.height); 83 | float area_intersect = w * h; 84 | float area_union = area1 + area2 - area_intersect; 85 | if (static_cast(area_intersect) / area_union > iou_thresh) { 86 | mask_merged[i] = 1; 87 | bboxes_nms->back().score_ += (*bboxes)[i].score_; 88 | } 89 | } 90 | } 91 | } 92 | 93 | } // namespace fd 94 | } // namespace seeta 95 | -------------------------------------------------------------------------------- /cpp_modules/openpose/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(core) 2 | add_subdirectory(utilities) 3 | add_subdirectory(face) 4 | set_target_properties(core utilities face PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS}) 5 | 6 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cuda_add_library(core 2 | array.cpp 3 | cvMatToOpInput.cpp 4 | cvMatToOpOutput.cpp 5 | datum.cpp 6 | keypointScaler.cpp 7 | maximumBase.cpp 8 | maximumBase.cu 9 | maximumCaffe.cpp 10 | netCaffe.cpp 11 | nmsBase.cpp 12 | nmsBase.cu 13 | nmsCaffe.cpp 14 | opOutputToCvMat.cpp 15 | point.cpp 16 | rectangle.cpp 17 | renderer.cpp 18 | resizeAndMergeBase.cpp 19 | resizeAndMergeBase.cu 20 | resizeAndMergeCaffe.cpp) 21 | target_link_libraries(core caffe) 22 | 23 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_COMMON_HPP 2 | #define OPENPOSE_CORE_COMMON_HPP 3 | 4 | // Std library most used classes 5 | #include 6 | #include // std::shared_ptr 7 | #include 8 | #include 9 | // OpenPose most used classes 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | // Macros at the end, otherwise circular dependency with array, point & rectangle 16 | #include 17 | 18 | #endif // OPENPOSE_CORE_COMMON_HPP 19 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/cvMatToOpInput.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace op 6 | { 7 | CvMatToOpInput::CvMatToOpInput(const Point& netInputResolution, const int scaleNumber, const float scaleGap) : 8 | mScaleNumber{scaleNumber}, 9 | mScaleGap{scaleGap}, 10 | mInputNetSize4D{{mScaleNumber, 3, netInputResolution.y, netInputResolution.x}} 11 | { 12 | try 13 | { 14 | // Security checks 15 | if (netInputResolution.x % 16 != 0 || netInputResolution.y % 16 != 0) 16 | error("Net input resolution must be multiples of 16.", __LINE__, __FUNCTION__, __FILE__); 17 | } 18 | catch (const std::exception& e) 19 | { 20 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 21 | } 22 | } 23 | 24 | std::pair, std::vector> CvMatToOpInput::format(const cv::Mat& cvInputData) const 25 | { 26 | try 27 | { 28 | // Security checks 29 | if (cvInputData.empty()) 30 | error("Wrong input element (empty cvInputData).", __LINE__, __FUNCTION__, __FILE__); 31 | if (cvInputData.channels() != 3) 32 | error("Input images must be 3-channel BGR.", __LINE__, __FUNCTION__, __FILE__); 33 | 34 | // inputNetData - Reescale keeping aspect ratio and transform to float the input deep net image 35 | Array inputNetData{mInputNetSize4D}; 36 | std::vector scaleRatios(mScaleNumber, 1.f); 37 | const auto inputNetDataOffset = inputNetData.getVolume(1, 3); 38 | for (auto i = 0; i < mScaleNumber; i++) 39 | { 40 | const auto currentScale = 1.f - i*mScaleGap; 41 | if (currentScale < 0.f || 1.f < currentScale) 42 | error("All scales must be in the range [0, 1], i.e. 0 <= 1-scale_number*scale_gap <= 1", __LINE__, __FUNCTION__, __FILE__); 43 | 44 | const auto netInputWidth = inputNetData.getSize(3); 45 | const auto targetWidth = fastTruncate(intRound(netInputWidth * currentScale) / 16 * 16, 1, netInputWidth); 46 | const auto netInputHeight = inputNetData.getSize(2); 47 | const auto targetHeight = fastTruncate(intRound(netInputHeight * currentScale) / 16 * 16, 1, netInputHeight); 48 | const Point targetSize{targetWidth, targetHeight}; 49 | const auto scale = resizeGetScaleFactor(Point{cvInputData.cols, cvInputData.rows}, targetSize); 50 | const cv::Mat frameWithNetSize = resizeFixedAspectRatio(cvInputData, scale, Point{netInputWidth, netInputHeight}); 51 | // Fill inputNetData 52 | uCharCvMatToFloatPtr(inputNetData.getPtr() + i * inputNetDataOffset, frameWithNetSize, true); 53 | // Fill scaleRatios 54 | scaleRatios[i] = {(float)scale}; 55 | if (i > 0) 56 | scaleRatios[i] /= scaleRatios[0]; 57 | } 58 | scaleRatios.at(0) /= scaleRatios[0]; 59 | return std::make_pair(inputNetData, scaleRatios); 60 | } 61 | catch (const std::exception& e) 62 | { 63 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 64 | return std::make_pair(Array{}, std::vector{}); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/cvMatToOpInput.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP 2 | #define OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP 3 | 4 | #include // std::pair 5 | #include // cv::Mat 6 | #include 7 | 8 | namespace op 9 | { 10 | class OP_API CvMatToOpInput 11 | { 12 | public: 13 | CvMatToOpInput(const Point& netInputResolution, const int scaleNumber = 1, const float scaleGap = 0.25); 14 | 15 | std::pair, std::vector> format(const cv::Mat& cvInputData) const; 16 | 17 | private: 18 | const int mScaleNumber; 19 | const float mScaleGap; 20 | const std::vector mInputNetSize4D; 21 | }; 22 | } 23 | 24 | #endif // OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP 25 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/cvMatToOpOutput.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace op 5 | { 6 | CvMatToOpOutput::CvMatToOpOutput(const Point& outputResolution, const bool generateOutput) : 7 | mGenerateOutput{generateOutput}, 8 | mOutputSize3D{{3, outputResolution.y, outputResolution.x}} 9 | { 10 | } 11 | 12 | std::tuple> CvMatToOpOutput::format(const cv::Mat& cvInputData) const 13 | { 14 | try 15 | { 16 | // Security checks 17 | if (cvInputData.empty()) 18 | error("Wrong input element (empty cvInputData).", __LINE__, __FUNCTION__, __FILE__); 19 | if (cvInputData.channels() != 3) 20 | error("Input images must be 3-channel BGR.", __LINE__, __FUNCTION__, __FILE__); 21 | 22 | // outputData - Reescale keeping aspect ratio and transform to float the output image 23 | const Point outputResolution{mOutputSize3D[2], mOutputSize3D[1]}; 24 | const double scaleInputToOutput = resizeGetScaleFactor(Point{cvInputData.cols, cvInputData.rows}, outputResolution); 25 | const cv::Mat frameWithOutputSize = resizeFixedAspectRatio(cvInputData, scaleInputToOutput, outputResolution); 26 | Array outputData; 27 | if (mGenerateOutput) 28 | { 29 | outputData.reset(mOutputSize3D); 30 | uCharCvMatToFloatPtr(outputData.getPtr(), frameWithOutputSize, false); 31 | } 32 | 33 | return std::make_tuple(scaleInputToOutput, outputData); 34 | } 35 | catch (const std::exception& e) 36 | { 37 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 38 | return std::make_tuple(0., Array{}); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/cvMatToOpOutput.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP 2 | #define OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP 3 | 4 | #include // cv::Mat 5 | #include 6 | 7 | namespace op 8 | { 9 | class OP_API CvMatToOpOutput 10 | { 11 | public: 12 | CvMatToOpOutput(const Point& outputResolution, const bool generateOutput = true); 13 | 14 | std::tuple> format(const cv::Mat& cvInputData) const; 15 | 16 | private: 17 | const bool mGenerateOutput; 18 | const std::vector mOutputSize3D; 19 | }; 20 | } 21 | 22 | #endif // OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP 23 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/enumClasses.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_ENUM_CLASSES_HPP 2 | #define OPENPOSE_CORE_ENUM_CLASSES_HPP 3 | 4 | namespace op 5 | { 6 | enum class ScaleMode : unsigned char 7 | { 8 | InputResolution, 9 | NetOutputResolution, 10 | OutputResolution, 11 | ZeroToOne, // [0, 1] 12 | PlusMinusOne, // [-1, 1] 13 | UnsignedChar, // [0, 255] 14 | }; 15 | 16 | enum class HeatMapType : unsigned char 17 | { 18 | Parts, 19 | Background, 20 | PAFs, 21 | }; 22 | 23 | enum class RenderMode : unsigned char 24 | { 25 | None, 26 | Cpu, 27 | Gpu, 28 | }; 29 | } 30 | 31 | #endif // OPENPOSE_CORE_ENUM_CLASSES_HPP 32 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/headers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_HEADERS_HPP 2 | #define OPENPOSE_CORE_HEADERS_HPP 3 | 4 | // core module 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #endif // OPENPOSE_CORE_HEADERS_HPP 24 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/keypointScaler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace op 5 | { 6 | KeypointScaler::KeypointScaler(const ScaleMode scaleMode) : 7 | mScaleMode{scaleMode} 8 | { 9 | } 10 | 11 | void KeypointScaler::scale(Array& arrayToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point& producerSize) const 12 | { 13 | try 14 | { 15 | std::vector> arrayToScalesToScale{arrayToScale}; 16 | scale(arrayToScalesToScale, scaleInputToOutput, scaleNetToOutput, producerSize); 17 | } 18 | catch (const std::exception& e) 19 | { 20 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 21 | } 22 | } 23 | 24 | void KeypointScaler::scale(std::vector>& arrayToScalesToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point& producerSize) const 25 | { 26 | try 27 | { 28 | if (mScaleMode != ScaleMode::OutputResolution) 29 | { 30 | // InputResolution 31 | if (mScaleMode == ScaleMode::InputResolution) 32 | for (auto& arrayToScale : arrayToScalesToScale) 33 | scaleKeypoints(arrayToScale, 1.f/scaleInputToOutput); 34 | // NetOutputResolution 35 | else if (mScaleMode == ScaleMode::NetOutputResolution) 36 | for (auto& arrayToScale : arrayToScalesToScale) 37 | scaleKeypoints(arrayToScale, 1.f/scaleNetToOutput); 38 | // [0,1] 39 | else if (mScaleMode == ScaleMode::ZeroToOne) 40 | { 41 | const auto scale = 1.f/scaleInputToOutput; 42 | const auto scaleX = scale / ((float)producerSize.x - 1.f); 43 | const auto scaleY = scale / ((float)producerSize.y - 1.f); 44 | for (auto& arrayToScale : arrayToScalesToScale) 45 | scaleKeypoints(arrayToScale, scaleX, scaleY); 46 | } 47 | // [-1,1] 48 | else if (mScaleMode == ScaleMode::PlusMinusOne) 49 | { 50 | const auto scale = 2.f/scaleInputToOutput; 51 | const auto scaleX = (scale / ((float)producerSize.x - 1.f)); 52 | const auto scaleY = (scale / ((float)producerSize.y - 1.f)); 53 | const auto offset = -1.f; 54 | for (auto& arrayToScale : arrayToScalesToScale) 55 | scaleKeypoints(arrayToScale, scaleX, scaleY, offset, offset); 56 | } 57 | // Unknown 58 | else 59 | error("Unknown ScaleMode selected.", __LINE__, __FUNCTION__, __FILE__); 60 | } 61 | } 62 | catch (const std::exception& e) 63 | { 64 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/keypointScaler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_KEYPOINT_SCALER_HPP 2 | #define OPENPOSE_CORE_KEYPOINT_SCALER_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace op 8 | { 9 | class OP_API KeypointScaler 10 | { 11 | public: 12 | explicit KeypointScaler(const ScaleMode scaleMode); 13 | 14 | void scale(Array& arrayToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point& producerSize) const; 15 | 16 | void scale(std::vector>& arraysToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point& producerSize) const; 17 | 18 | private: 19 | const ScaleMode mScaleMode; 20 | }; 21 | } 22 | 23 | #endif // OPENPOSE_CORE_KEYPOINT_SCALER_HPP 24 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/macros.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_MACROS_HPP 2 | #define OPENPOSE_CORE_MACROS_HPP 3 | 4 | #ifndef _WIN32 5 | #define OP_API 6 | #elif defined OP_EXPORTS 7 | #define OP_API __declspec(dllexport) 8 | #else 9 | #define OP_API __declspec(dllimport) 10 | #endif 11 | 12 | //Disable some Windows Warnings 13 | #ifdef _WIN32 14 | #pragma warning ( disable : 4251 ) // XXX needs to have dll-interface to be used by clients of class YYY 15 | #pragma warning( disable: 4275 ) // non dll-interface structXXX used as base 16 | #endif 17 | 18 | #define DATUM_BASE_NO_PTR std::vector 19 | #define DATUM_BASE std::shared_ptr 20 | #define DEFINE_TEMPLATE_DATUM(templateName) template class OP_API templateName 21 | //#define COMPILE_TEMPLATE_DATUM(templateName) extern DEFINE_TEMPLATE_DATUM(templateName) 22 | 23 | #define UNUSED(unusedVariable) (void)(unusedVariable) 24 | 25 | #define DELETE_COPY(className) \ 26 | className(const className&) = delete; \ 27 | className& operator=(const className&) = delete 28 | 29 | #define COMPILE_TEMPLATE_BASIC_TYPES_CLASS(className) COMPILE_TEMPLATE_BASIC_TYPES(className, class) 30 | 31 | #define COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(className) COMPILE_TEMPLATE_BASIC_TYPES(className, struct) 32 | 33 | #define COMPILE_TEMPLATE_BASIC_TYPES(className, classType) \ 34 | template classType OP_API className; \ 35 | template classType OP_API className; \ 36 | template classType OP_API className; \ 37 | template classType OP_API className; \ 38 | template classType OP_API className; \ 39 | template classType OP_API className; \ 40 | template classType OP_API className; \ 41 | template classType OP_API className; \ 42 | template classType OP_API className; \ 43 | template classType OP_API className; \ 44 | template classType OP_API className; \ 45 | template classType OP_API className; \ 46 | template classType OP_API className; \ 47 | template classType OP_API className 48 | 49 | // Includes at the end, since this macros class does not need them, but the files that call this 50 | // file. However, keeping the files at the beginning might create a circular include linking problem. 51 | #include // std::shared_ptr 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #endif // OPENPOSE_CORE_MACROS_HPP 58 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/maximumBase.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | #include 3 | 4 | namespace op 5 | { 6 | template 7 | void maximumCpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const std::array& targetSize, const std::array& sourceSize) 8 | { 9 | try 10 | { 11 | UNUSED(targetPtr); 12 | UNUSED(kernelPtr); 13 | UNUSED(sourcePtr); 14 | UNUSED(targetSize); 15 | UNUSED(sourceSize); 16 | error("CPU version not completely implemented.", __LINE__, __FUNCTION__, __FILE__); 17 | 18 | // // TODO: ideally done, try, debug & compare to *.cu 19 | // TODO: (maybe): remove thrust dependencies for computers without CUDA? 20 | // const auto height = sourceSize[2]; 21 | // const auto width = sourceSize[3]; 22 | // const auto imageOffset = height * width; 23 | // const auto num = targetSize[0]; 24 | // const auto channels = targetSize[1]; 25 | // const auto numberParts = targetSize[2]; 26 | // const auto numberSubparts = targetSize[3]; 27 | 28 | // // log("sourceSize[0]: " + std::to_string(sourceSize[0])); // = 1 29 | // // log("sourceSize[1]: " + std::to_string(sourceSize[1])); // = #body parts + bck = 22 (hands) or 71 (face) 30 | // // log("sourceSize[2]: " + std::to_string(sourceSize[2])); // = 368 = height 31 | // // log("sourceSize[3]: " + std::to_string(sourceSize[3])); // = 368 = width 32 | // // log("targetSize[0]: " + std::to_string(targetSize[0])); // = 1 33 | // // log("targetSize[1]: " + std::to_string(targetSize[1])); // = 1 34 | // // log("targetSize[2]: " + std::to_string(targetSize[2])); // = 21(hands) or 70 (face) 35 | // // log("targetSize[3]: " + std::to_string(targetSize[3])); // = 3 = [x, y, score] 36 | // // log(" "); 37 | // for (auto n = 0; n < num; n++) 38 | // { 39 | // for (auto c = 0; c < channels; c++) 40 | // { 41 | // // // Parameters 42 | // const auto offsetChannel = (n * channels + c); 43 | // for (auto part = 0; part < numberParts; part++) 44 | // { 45 | // auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts; 46 | // const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset; 47 | // // Option a - 6.3 fps 48 | // const auto sourceIndexIterator = thrust::max_element(thrust::host, sourcePtrOffsetted, sourcePtrOffsetted + imageOffset); 49 | // const auto sourceIndex = (int)(sourceIndexIterator - sourcePtrOffsetted); 50 | // targetPtrOffsetted[0] = sourceIndex % width; 51 | // targetPtrOffsetted[1] = sourceIndex / width; 52 | // targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex]; 53 | // } 54 | // } 55 | // } 56 | } 57 | catch (const std::exception& e) 58 | { 59 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 60 | } 61 | } 62 | 63 | template void maximumCpu(float* targetPtr, int* kernelPtr, const float* const sourcePtr, const std::array& targetSize, const std::array& sourceSize); 64 | template void maximumCpu(double* targetPtr, int* kernelPtr, const double* const sourcePtr, const std::array& targetSize, const std::array& sourceSize); 65 | } 66 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/maximumBase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_MAXIMUM_BASE_HPP 2 | #define OPENPOSE_CORE_MAXIMUM_BASE_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | template 9 | OP_API void maximumCpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, const std::array& sourceSize); 10 | 11 | template 12 | OP_API void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, const std::array& sourceSize); 13 | } 14 | 15 | #endif // OPENPOSE_CORE_MAXIMUM_BASE_HPP 16 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/maximumCaffe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace op 5 | { 6 | template 7 | MaximumCaffe::MaximumCaffe() 8 | { 9 | } 10 | 11 | template 12 | void MaximumCaffe::LayerSetUp(const std::vector*>& bottom, const std::vector*>& top) 13 | { 14 | try 15 | { 16 | if (top.size() != 1) 17 | error("top.size() != 1", __LINE__, __FUNCTION__, __FILE__); 18 | if (bottom.size() != 1) 19 | error("bottom.size() != 1", __LINE__, __FUNCTION__, __FILE__); 20 | } 21 | catch (const std::exception& e) 22 | { 23 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 24 | } 25 | } 26 | 27 | template 28 | void MaximumCaffe::Reshape(const std::vector*>& bottom, const std::vector*>& top) 29 | { 30 | try 31 | { 32 | auto bottomBlob = bottom.at(0); 33 | auto topBlob = top.at(0); 34 | 35 | // Bottom shape 36 | std::vector bottomShape = bottomBlob->shape(); 37 | 38 | // Top shape 39 | std::vector topShape{bottomShape}; 40 | topShape[1] = 1; // Unnecessary 41 | topShape[2] = bottomShape[1]-1; // Number parts + bck - 1 42 | topShape[3] = 3; // X, Y, score 43 | topBlob->Reshape(topShape); 44 | 45 | // Array sizes 46 | mTopSize = std::array{topBlob->shape(0), topBlob->shape(1), topBlob->shape(2), topBlob->shape(3)}; 47 | mBottomSize = std::array{bottomBlob->shape(0), bottomBlob->shape(1), bottomBlob->shape(2), bottomBlob->shape(3)}; 48 | } 49 | catch (const std::exception& e) 50 | { 51 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 52 | } 53 | } 54 | 55 | template 56 | void MaximumCaffe::Forward_cpu(const std::vector*>& bottom, const std::vector*>& top) 57 | { 58 | try 59 | { 60 | maximumGpu(top.at(0)->mutable_cpu_data(), bottom.at(0)->cpu_data(), mTopSize, mBottomSize); 61 | } 62 | catch (const std::exception& e) 63 | { 64 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 65 | } 66 | } 67 | 68 | template 69 | void MaximumCaffe::Forward_gpu(const std::vector*>& bottom, const std::vector*>& top) 70 | { 71 | try 72 | { 73 | maximumGpu(top.at(0)->mutable_gpu_data(), bottom.at(0)->gpu_data(), mTopSize, mBottomSize); 74 | } 75 | catch (const std::exception& e) 76 | { 77 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 78 | } 79 | } 80 | 81 | template 82 | void MaximumCaffe::Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom) 83 | { 84 | try 85 | { 86 | UNUSED(top); 87 | UNUSED(propagate_down); 88 | UNUSED(bottom); 89 | NOT_IMPLEMENTED; 90 | } 91 | catch (const std::exception& e) 92 | { 93 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 94 | } 95 | } 96 | 97 | template 98 | void MaximumCaffe::Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom) 99 | { 100 | try 101 | { 102 | UNUSED(top); 103 | UNUSED(propagate_down); 104 | UNUSED(bottom); 105 | NOT_IMPLEMENTED; 106 | } 107 | catch (const std::exception& e) 108 | { 109 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 110 | } 111 | } 112 | 113 | INSTANTIATE_CLASS(MaximumCaffe); 114 | } -------------------------------------------------------------------------------- /cpp_modules/openpose/core/maximumCaffe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_MAXIMUM_CAFFE_HPP 2 | #define OPENPOSE_CORE_MAXIMUM_CAFFE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace op 8 | { 9 | // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep the compatibility with any generic Caffe version, 10 | // we keep this 'layer' inside our library rather than in the Caffe code. 11 | template 12 | class OP_API MaximumCaffe 13 | { 14 | public: 15 | explicit MaximumCaffe(); 16 | 17 | virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); 18 | 19 | virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top); 20 | 21 | virtual inline const char* type() const { return "Maximum"; } 22 | 23 | virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); 24 | 25 | virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); 26 | 27 | virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom); 28 | 29 | virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom); 30 | 31 | private: 32 | std::array mBottomSize; 33 | std::array mTopSize; 34 | }; 35 | } 36 | 37 | #endif // OPENPOSE_CORE_MAXIMUM_CAFFE_HPP 38 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/net.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_NET_HPP 2 | #define OPENPOSE_CORE_NET_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | class OP_API Net 9 | { 10 | public: 11 | virtual void initializationOnThread() = 0; 12 | 13 | // Alternative a) getInputDataCpuPtr or getInputDataGpuPtr + forwardPass() 14 | virtual float* getInputDataCpuPtr() const = 0; 15 | 16 | virtual float* getInputDataGpuPtr() const = 0; 17 | 18 | // Alternative b) 19 | virtual void forwardPass(const float* const inputData = nullptr) const = 0; 20 | }; 21 | } 22 | 23 | #endif // OPENPOSE_CORE_NET_HPP 24 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/netCaffe.cpp: -------------------------------------------------------------------------------- 1 | #include // std::accumulate 2 | #include 3 | #include 4 | 5 | namespace op 6 | { 7 | NetCaffe::NetCaffe(const std::array& netInputSize4D, const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId, const std::string& lastBlobName) : 8 | mGpuId{gpuId}, 9 | // mNetInputSize4D{netInputSize4D}, // This line crashes on some devices with old G++ 10 | mNetInputSize4D{netInputSize4D[0], netInputSize4D[1], netInputSize4D[2], netInputSize4D[3]}, 11 | mNetInputMemory{std::accumulate(mNetInputSize4D.begin(), mNetInputSize4D.end(), 1, std::multiplies()) * sizeof(float)}, 12 | mCaffeProto{caffeProto}, 13 | mCaffeTrainedModel{caffeTrainedModel}, 14 | mLastBlobName{lastBlobName} 15 | { 16 | } 17 | 18 | NetCaffe::~NetCaffe() 19 | { 20 | } 21 | 22 | void NetCaffe::initializationOnThread() 23 | { 24 | try 25 | { 26 | // Initialize net 27 | caffe::Caffe::set_mode(caffe::Caffe::GPU); 28 | caffe::Caffe::SetDevice(mGpuId); 29 | upCaffeNet.reset(new caffe::Net{mCaffeProto, caffe::TEST}); 30 | upCaffeNet->CopyTrainedLayersFrom(mCaffeTrainedModel); 31 | upCaffeNet->blobs()[0]->Reshape({mNetInputSize4D[0], mNetInputSize4D[1], mNetInputSize4D[2], mNetInputSize4D[3]}); 32 | upCaffeNet->Reshape(); 33 | cudaCheck(__LINE__, __FUNCTION__, __FILE__); 34 | // Set spOutputBlob 35 | spOutputBlob = upCaffeNet->blob_by_name(mLastBlobName); 36 | if (spOutputBlob == nullptr) 37 | error("The output blob is a nullptr. Did you use the same name than the prototxt? (Used: " + mLastBlobName + ").", __LINE__, __FUNCTION__, __FILE__); 38 | cudaCheck(__LINE__, __FUNCTION__, __FILE__); 39 | } 40 | catch (const std::exception& e) 41 | { 42 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 43 | } 44 | } 45 | 46 | float* NetCaffe::getInputDataCpuPtr() const 47 | { 48 | try 49 | { 50 | return upCaffeNet->blobs().at(0)->mutable_cpu_data(); 51 | } 52 | catch (const std::exception& e) 53 | { 54 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 55 | return nullptr; 56 | } 57 | } 58 | 59 | float* NetCaffe::getInputDataGpuPtr() const 60 | { 61 | try 62 | { 63 | return upCaffeNet->blobs().at(0)->mutable_gpu_data(); 64 | } 65 | catch (const std::exception& e) 66 | { 67 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 68 | return nullptr; 69 | } 70 | } 71 | 72 | void NetCaffe::forwardPass(const float* const inputData) const 73 | { 74 | try 75 | { 76 | // Copy frame data to GPU memory 77 | if (inputData != nullptr) 78 | { 79 | auto* gpuImagePtr = upCaffeNet->blobs().at(0)->mutable_gpu_data(); 80 | cudaMemcpy(gpuImagePtr, inputData, mNetInputMemory, cudaMemcpyHostToDevice); 81 | } 82 | // Perform deep network forward pass 83 | upCaffeNet->ForwardFrom(0); 84 | cudaCheck(__LINE__, __FUNCTION__, __FILE__); 85 | } 86 | catch (const std::exception& e) 87 | { 88 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 89 | } 90 | } 91 | 92 | boost::shared_ptr> NetCaffe::getOutputBlob() const 93 | { 94 | try 95 | { 96 | return spOutputBlob; 97 | } 98 | catch (const std::exception& e) 99 | { 100 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 101 | return nullptr; 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /cpp_modules/openpose/core/netCaffe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_NET_CAFFE_HPP 2 | #define OPENPOSE_CORE_NET_CAFFE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace op 9 | { 10 | class OP_API NetCaffe : public Net 11 | { 12 | public: 13 | NetCaffe(const std::array& netInputSize4D, const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId = 0, 14 | const std::string& lastBlobName = "net_output"); 15 | 16 | virtual ~NetCaffe(); 17 | 18 | void initializationOnThread(); 19 | 20 | // Alternative a) getInputDataCpuPtr or getInputDataGpuPtr + forwardPass 21 | float* getInputDataCpuPtr() const; 22 | 23 | float* getInputDataGpuPtr() const; 24 | 25 | // Alternative b) 26 | void forwardPass(const float* const inputNetData = nullptr) const; 27 | 28 | boost::shared_ptr> getOutputBlob() const; 29 | 30 | private: 31 | // Init with constructor 32 | const int mGpuId; 33 | const std::array mNetInputSize4D; 34 | const unsigned long mNetInputMemory; 35 | const std::string mCaffeProto; 36 | const std::string mCaffeTrainedModel; 37 | const std::string mLastBlobName; 38 | // Init with thread 39 | std::unique_ptr> upCaffeNet; 40 | boost::shared_ptr> spOutputBlob; 41 | 42 | DELETE_COPY(NetCaffe); 43 | }; 44 | } 45 | 46 | #endif // OPENPOSE_CORE_NET_CAFFE_HPP -------------------------------------------------------------------------------- /cpp_modules/openpose/core/nmsBase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace op 4 | { 5 | template 6 | void nmsCpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, const std::array& sourceSize) 7 | { 8 | try 9 | { 10 | UNUSED(targetPtr); 11 | UNUSED(kernelPtr); 12 | UNUSED(sourcePtr); 13 | UNUSED(threshold); 14 | UNUSED(targetSize); 15 | UNUSED(sourceSize); 16 | error("CPU version not completely implemented.", __LINE__, __FUNCTION__, __FILE__); 17 | 18 | // TODO: THIS CODE IS WORKING, BUT IT DOES NOT CONSIDER THE MAX NUMBER OF PEAKS 19 | // const int num = bottom->shape(0); 20 | // //const int channel = bottom->shape(1); 21 | // const int oriSpatialHeight = bottom->shape(2); 22 | // const int oriSpatialWidth = bottom->shape(3); 23 | 24 | // T* dst_pointer = top->mutable_cpu_data(); 25 | // const T* const src_pointer = bottom->cpu_data(); 26 | // const int offset2 = oriSpatialHeight * oriSpatialWidth; 27 | // const int offset2_dst = (mMaxPeaks+1)*2; 28 | 29 | //stupid method 30 | // for (int n = 0; n < num; n++) 31 | // { 32 | // //assume only one channel 33 | // int peakCount = 0; 34 | // for (int y = 0; y < oriSpatialHeight; y++) 35 | // { 36 | // for (int x = 0; x < oriSpatialWidth; x++) 37 | // { 38 | // const T value = src_pointer[n * offset2 + y*oriSpatialWidth + x]; 39 | // if (value >= mThreshold) 40 | // { 41 | // const T top = (y == 0) ? 0 : src_pointer[n * offset2 + (y-1)*oriSpatialWidth + x]; 42 | // const T bottom = (y == oriSpatialHeight - 1) ? 0 : src_pointer[n * offset2 + (y+1)*oriSpatialWidth + x]; 43 | // const T left = (x == 0) ? 0 : src_pointer[n * offset2 + y*oriSpatialWidth + (x-1)]; 44 | // const T right = (x == oriSpatialWidth - 1) ? 0 : src_pointer[n * offset2 + y*oriSpatialWidth + (x+1)]; 45 | // if (value > top && value > bottom && value > left && value > right) 46 | // { 47 | // dst_pointer[n*offset2_dst + (peakCount + 1) * 2] = x; 48 | // dst_pointer[n*offset2_dst + (peakCount + 1) * 2 + 1] = y; 49 | // peakCount++; 50 | // } 51 | // } 52 | // } 53 | // } 54 | // dst_pointer[n*offset2_dst] = peakCount; 55 | // } 56 | } 57 | catch (const std::exception& e) 58 | { 59 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 60 | } 61 | } 62 | 63 | template void nmsCpu(float* targetPtr, int* kernelPtr, const float* const sourcePtr, const float threshold, const std::array& targetSize, const std::array& sourceSize); 64 | template void nmsCpu(double* targetPtr, int* kernelPtr, const double* const sourcePtr, const double threshold, const std::array& targetSize, const std::array& sourceSize); 65 | } 66 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/nmsBase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_NMS_BASE_HPP 2 | #define OPENPOSE_CORE_NMS_BASE_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | template 9 | OP_API void nmsCpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, const std::array& sourceSize); 10 | 11 | template 12 | OP_API void nmsGpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, const std::array& sourceSize); 13 | } 14 | 15 | #endif // OPENPOSE_CORE_NMS_BASE_HPP 16 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/nmsCaffe.hpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_CAFFE 2 | #ifndef OPENPOSE_CORE_NMS_CAFFE_HPP 3 | #define OPENPOSE_CORE_NMS_CAFFE_HPP 4 | 5 | #include 6 | #include 7 | 8 | namespace op 9 | { 10 | // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep the compatibility with any generic Caffe version, 11 | // we keep this 'layer' inside our library rather than in the Caffe code. 12 | template 13 | class OP_API NmsCaffe 14 | { 15 | public: 16 | explicit NmsCaffe(); 17 | 18 | virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); 19 | 20 | virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top, const int maxPeaks); 21 | 22 | virtual inline const char* type() const { return "Nms"; } 23 | 24 | void setThreshold(const T threshold); 25 | 26 | virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); 27 | 28 | virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); 29 | 30 | virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom); 31 | 32 | virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, const std::vector*>& bottom); 33 | 34 | private: 35 | T mThreshold; 36 | caffe::Blob mKernelBlob; 37 | std::array mBottomSize; 38 | std::array mTopSize; 39 | }; 40 | } 41 | 42 | #endif // OPENPOSE_CORE_NMS_CAFFE_HPP 43 | #endif 44 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/opOutputToCvMat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace op 5 | { 6 | OpOutputToCvMat::OpOutputToCvMat(const Point& outputResolution) : 7 | mOutputResolution{outputResolution.x, outputResolution.y, 3} 8 | { 9 | } 10 | 11 | cv::Mat OpOutputToCvMat::formatToCvMat(const Array& outputData) const 12 | { 13 | try 14 | { 15 | // Security checks 16 | if (outputData.empty()) 17 | error("Wrong input element (empty outputData).", __LINE__, __FUNCTION__, __FILE__); 18 | 19 | cv::Mat cvMat; 20 | floatPtrToUCharCvMat(cvMat, outputData.getConstPtr(), mOutputResolution); 21 | 22 | return cvMat; 23 | } 24 | catch (const std::exception& e) 25 | { 26 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 27 | return cv::Mat(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/opOutputToCvMat.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP 2 | #define OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP 3 | 4 | #include // cv::Mat 5 | #include 6 | 7 | namespace op 8 | { 9 | class OP_API OpOutputToCvMat 10 | { 11 | public: 12 | explicit OpOutputToCvMat(const Point& outputResolution); 13 | 14 | cv::Mat formatToCvMat(const Array& outputData) const; 15 | 16 | private: 17 | const std::array mOutputResolution; 18 | }; 19 | } 20 | 21 | #endif // OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP 22 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/rectangle.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_RECTANGLE_HPP 2 | #define OPENPOSE_CORE_RECTANGLE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace op 8 | { 9 | template 10 | struct Rectangle 11 | { 12 | T x; 13 | T y; 14 | T width; 15 | T height; 16 | 17 | Rectangle(const T x = 0, const T y = 0, const T width = 0, const T height = 0); 18 | 19 | /** 20 | * Copy constructor. 21 | * It performs `fast copy`: For performance purpose, copying a Rectangle or Datum or cv::Mat just copies the reference, it still shares the same internal data. 22 | * Modifying the copied element will modify the original one. 23 | * Use clone() for a slower but real copy, similarly to cv::Mat and Rectangle. 24 | * @param rectangle Rectangle to be copied. 25 | */ 26 | Rectangle(const Rectangle& rectangle); 27 | 28 | /** 29 | * Copy assignment. 30 | * Similar to Rectangle(const Rectangle& rectangle). 31 | * @param rectangle Rectangle to be copied. 32 | * @return The resulting Rectangle. 33 | */ 34 | Rectangle& operator=(const Rectangle& rectangle); 35 | 36 | /** 37 | * Move constructor. 38 | * It destroys the original Rectangle to be moved. 39 | * @param rectangle Rectangle to be moved. 40 | */ 41 | Rectangle(Rectangle&& rectangle); 42 | 43 | /** 44 | * Move assignment. 45 | * Similar to Rectangle(Rectangle&& rectangle). 46 | * @param rectangle Rectangle to be moved. 47 | * @return The resulting Rectangle. 48 | */ 49 | Rectangle& operator=(Rectangle&& rectangle); 50 | 51 | Point center() const; 52 | 53 | inline Point topLeft() const 54 | { 55 | return Point{x, y}; 56 | } 57 | 58 | Point bottomRight() const; 59 | 60 | inline T area() const 61 | { 62 | return width * height; 63 | } 64 | 65 | void recenter(const T newWidth, const T newHeight); 66 | 67 | /** 68 | * It returns a string with the whole Rectangle data. Useful for debugging. 69 | * The format is: `[x, y, width, height]` 70 | * @return A string with the Rectangle values in the above format. 71 | */ 72 | std::string toString() const; 73 | 74 | // -------------------------------------------------- Basic Operators -------------------------------------------------- // 75 | Rectangle& operator*=(const T value); 76 | 77 | Rectangle operator*(const T value) const; 78 | 79 | Rectangle& operator/=(const T value); 80 | 81 | Rectangle operator/(const T value) const; 82 | }; 83 | 84 | // Static methods 85 | template 86 | Rectangle recenter(const Rectangle& rectangle, const T newWidth, const T newHeight); 87 | } 88 | 89 | #endif // OPENPOSE_CORE_RECTANGLE_HPP 90 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/renderer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_RENDERER_HPP 2 | #define OPENPOSE_CORE_RENDERER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace op 9 | { 10 | class OP_API Renderer 11 | { 12 | public: 13 | explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, 14 | const unsigned int elementToRender = 0u, const unsigned int numberElementsToRender = 0u); 15 | 16 | ~Renderer(); 17 | 18 | void initializationOnThread(); 19 | 20 | void increaseElementToRender(const int increment); 21 | 22 | void setElementToRender(const int elementToRender); 23 | 24 | std::tuple, std::shared_ptr, std::shared_ptr>, 25 | std::shared_ptr> getSharedParameters(); 26 | 27 | void setSharedParametersAndIfLast(const std::tuple, std::shared_ptr, 28 | std::shared_ptr>, 29 | std::shared_ptr>& tuple, const bool isLast); 30 | 31 | float getAlphaKeypoint() const; 32 | 33 | void setAlphaKeypoint(const float alphaKeypoint); 34 | 35 | float getAlphaHeatMap() const; 36 | 37 | void setAlphaHeatMap(const float alphaHeatMap); 38 | 39 | protected: 40 | std::shared_ptr spGpuMemoryPtr; 41 | std::shared_ptr> spElementToRender; 42 | std::shared_ptr spNumberElementsToRender; 43 | 44 | void cpuToGpuMemoryIfNotCopiedYet(const float* const cpuMemory); 45 | 46 | void gpuToCpuMemoryIfLastRenderer(float* cpuMemory); 47 | 48 | private: 49 | const unsigned long long mVolume; 50 | float mAlphaKeypoint; 51 | float mAlphaHeatMap; 52 | bool mIsFirstRenderer; 53 | bool mIsLastRenderer; 54 | std::shared_ptr spGpuMemoryAllocated; 55 | 56 | DELETE_COPY(Renderer); 57 | }; 58 | } 59 | 60 | #endif // OPENPOSE_CORE_RENDERER_HPP 61 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/resizeAndMergeBase.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | #include 3 | 4 | namespace op 5 | { 6 | template 7 | void resizeAndMergeCpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, 8 | const std::array& sourceSize, const std::vector& scaleRatios) 9 | { 10 | try 11 | { 12 | UNUSED(targetPtr); 13 | UNUSED(sourcePtr); 14 | UNUSED(scaleRatios); 15 | UNUSED(targetSize); 16 | UNUSED(sourceSize); 17 | error("CPU version not completely implemented.", __LINE__, __FUNCTION__, __FILE__); 18 | 19 | // TODO: THIS CODE IS WORKING, BUT IT DOES NOT CONSIDER THE SCALES (I.E. SCALE NUMBER, START AND GAP) 20 | // const int num = bottom->shape(0); 21 | // const int channel = bottom->shape(1); 22 | // const int sourceHeight = bottom->shape(2); 23 | // const int sourceWidth = bottom->shape(3); 24 | // const int targetHeight = top->shape(2); 25 | // const int targetWidth = top->shape(3); 26 | 27 | // //stupid method 28 | // for (int n = 0; n < num; n++) 29 | // { 30 | // for (int c = 0; c < channel; c++) 31 | // { 32 | // //fill source 33 | // cv::Mat source(sourceWidth, sourceHeight, CV_32FC1); 34 | // const auto sourceOffsetChannel = sourceHeight * sourceWidth; 35 | // const auto sourceOffsetNum = sourceOffsetChannel * channel; 36 | // const auto sourceOffset = n*sourceOffsetNum + c*sourceOffsetChannel; 37 | // const T* const sourcePtr = bottom->cpu_data(); 38 | // for (int y = 0; y < sourceHeight; y++) 39 | // for (int x = 0; x < sourceWidth; x++) 40 | // source.at(x,y) = sourcePtr[sourceOffset + y*sourceWidth + x]; 41 | 42 | // // spatial resize 43 | // cv::Mat target; 44 | // cv::resize(source, target, {targetWidth, targetHeight}, 0, 0, CV_INTER_CUBIC); 45 | 46 | // //fill top 47 | // const auto targetOffsetChannel = targetHeight * targetWidth; 48 | // const auto targetOffsetNum = targetOffsetChannel * channel; 49 | // const auto targetOffset = n*targetOffsetNum + c*targetOffsetChannel; 50 | // T* targetPtr = top->mutable_cpu_data(); 51 | // for (int y = 0; y < targetHeight; y++) 52 | // for (int x = 0; x < targetWidth; x++) 53 | // targetPtr[targetOffset + y*targetWidth + x] = target.at(x,y); 54 | // } 55 | // } 56 | } 57 | catch (const std::exception& e) 58 | { 59 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 60 | } 61 | } 62 | 63 | template void resizeAndMergeCpu(float* targetPtr, const float* const sourcePtr, const std::array& targetSize, 64 | const std::array& sourceSize, const std::vector& scaleRatios); 65 | template void resizeAndMergeCpu(double* targetPtr, const double* const sourcePtr, const std::array& targetSize, 66 | const std::array& sourceSize, const std::vector& scaleRatios); 67 | } 68 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/resizeAndMergeBase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP 2 | #define OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | template 9 | OP_API void resizeAndMergeCpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, const std::array& sourceSize, 10 | const std::vector& scaleRatios = {1}); 11 | 12 | template 13 | OP_API void resizeAndMergeGpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, const std::array& sourceSize, 14 | const std::vector& scaleRatios = {1}); 15 | } 16 | 17 | #endif // OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP 18 | -------------------------------------------------------------------------------- /cpp_modules/openpose/core/resizeAndMergeCaffe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP 2 | #define OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace op 8 | { 9 | // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep the 10 | // compatibility with any generic Caffe version, 11 | // we keep this 'layer' inside our library rather than in the Caffe code. 12 | template 13 | class OP_API ResizeAndMergeCaffe 14 | { 15 | public: 16 | explicit ResizeAndMergeCaffe(); 17 | 18 | virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); 19 | 20 | virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top, 21 | const float factor, const bool mergeFirstDimension = true); 22 | 23 | virtual inline const char* type() const { return "ResizeAndMerge"; } 24 | 25 | void setScaleRatios(const std::vector& scaleRatios); 26 | 27 | virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); 28 | 29 | virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); 30 | 31 | virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, 32 | const std::vector*>& bottom); 33 | 34 | virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, 35 | const std::vector*>& bottom); 36 | 37 | private: 38 | std::vector mScaleRatios; 39 | std::array mBottomSize; 40 | std::array mTopSize; 41 | 42 | DELETE_COPY(ResizeAndMergeCaffe); 43 | }; 44 | } 45 | 46 | #endif // OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP 47 | -------------------------------------------------------------------------------- /cpp_modules/openpose/face/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES faceExtractor.cpp) 2 | cuda_add_library(face ${SOURCES}) 3 | -------------------------------------------------------------------------------- /cpp_modules/openpose/face/faceExtractor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_FACE_FACE_EXTRACTOR_HPP 2 | #define OPENPOSE_FACE_FACE_EXTRACTOR_HPP 3 | 4 | #include 5 | #include 6 | #include // cv::Mat 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace op 13 | { 14 | class OP_API FaceExtractor 15 | { 16 | public: 17 | explicit FaceExtractor(const Point& netInputSize, 18 | const Point& netOutputSize, 19 | const std::string& init_net, 20 | const std::string& predict_net, 21 | const int gpuId); 22 | void initializationOnThread(); 23 | void forwardPass(const std::vector>& faceRectangles, const cv::Mat& cvInputData, const float scaleInputToOutput); 24 | Array getFaceKeypoints() const; 25 | 26 | private: 27 | const Point mNetOutputSize; 28 | const Point mOutputSize; 29 | std::shared_ptr spNet; 30 | std::shared_ptr> spResizeAndMergeCaffe; 31 | std::shared_ptr> spMaximumCaffe; 32 | Array mFaceImageCrop; 33 | Array mFaceKeypoints; 34 | // Init with thread 35 | boost::shared_ptr> spCaffeNetOutputBlob; 36 | std::shared_ptr> spHeatMapsBlob; 37 | std::shared_ptr> spPeaksBlob; 38 | std::thread::id mThreadId; 39 | 40 | void checkThread() const; 41 | DELETE_COPY(FaceExtractor); 42 | }; 43 | } 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | #endif // OPENPOSE_FACE_FACE_EXTRACTOR_HPP 56 | -------------------------------------------------------------------------------- /cpp_modules/openpose/face/faceParameters.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_FACE_FACE_PARAMETERS_HPP 2 | #define OPENPOSE_FACE_FACE_PARAMETERS_HPP 3 | 4 | 5 | namespace op 6 | { 7 | const auto FACE_MAX_FACES = 96u; 8 | const auto FACE_NUMBER_PARTS = 68u; 9 | #define FACE_PAIRS_RENDER_GPU {0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \ 10 | 20,21, 22,23, 23,24, 24,25, 25,26, 27,28, 28,29, 29,30, 31,32, 32,33, 33,34, 34,35, 36,37, 37,38, 38,39, 39,40, 40,41, \ 11 | 41,36, 42,43, 43,44, 44,45, 45,46, 46,47, 47,42, 48,49, 49,50, 50,51, 51,52, 52,53, 53,54, 54,55, 55,56, 56,57, 57,58, \ 12 | 58,59, 59,48, 60,61, 61,62, 62,63, 63,64, 64,65, 65,66, 66,67, 67,60} 13 | const std::vector FACE_PAIRS_RENDER {FACE_PAIRS_RENDER_GPU}; 14 | #define FACE_COLORS_RENDER_GPU 255.f, 255.f, 255.f 15 | const std::vector FACE_COLORS_RENDER{FACE_COLORS_RENDER_GPU}; 16 | 17 | const std::vector EYE_INDEX = { 18 | 36, 37, 38, 39, 40, 41, 19 | 42, 43, 44, 45, 46, 47 20 | }; 21 | 22 | const std::vector NOSE_INDEX = { 23 | 27, 28, 29, 30, 31, 32, 33, 34, 35 24 | }; 25 | 26 | const std::vector LIP_INDEX = { 27 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 28 | }; 29 | 30 | const std::vector> UPPER_LOWER_LIP_PAIRS = { 31 | {49, 59}, 32 | {50, 58}, 33 | {51, 57}, 34 | {52, 56}, 35 | {53, 55}, 36 | {61, 67}, 37 | {62, 66}, 38 | {63, 65} 39 | }; 40 | 41 | // Constant parameters 42 | const auto FACE_CCN_DECREASE_FACTOR = 8.f; 43 | const std::string FACE_PROTOTXT{"face/pose_deploy.prototxt"}; 44 | const std::string FACE_TRAINED_MODEL{"face/pose_iter_116000.caffemodel"}; 45 | 46 | // Rendering parameters 47 | const auto FACE_DEFAULT_ALPHA_KEYPOINT = 0.6f; 48 | const auto FACE_DEFAULT_ALPHA_HEAT_MAP = 0.7f; 49 | 50 | } 51 | 52 | #endif // OPENPOSE_FACE_FACE_PARAMETERS_HPP 53 | -------------------------------------------------------------------------------- /cpp_modules/openpose/face/op_face.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-25. 3 | // 4 | 5 | #ifndef CL_FACE_FACE_POSE_H 6 | #define CL_FACE_FACE_POSE_H 7 | 8 | #include "faceParameters.hpp" 9 | #include "faceExtractor.hpp" 10 | #include "cl_common.h" 11 | #include "cl_alignment.h" 12 | 13 | 14 | 15 | namespace op{ 16 | namespace fa{ 17 | 18 | class OPFace:public cl::fa::Alignment{ 19 | public: 20 | OPFace(int input_width = 320, int input_height = 320, int gpu_id = 0): 21 | input_width_(input_width), input_height_(input_height), gpu_id_(gpu_id) {} 22 | virtual ~OPFace(){} 23 | 24 | bool detect(const cv::Mat& src, 25 | const std::vector& windows, 26 | std::vector& result){ 27 | 28 | if(windows.size() <= 0){ 29 | return false; 30 | } 31 | 32 | std::vector> face_rectagenles(windows.size()); 33 | for(size_t i = 0; i < windows.size(); ++i){ 34 | face_rectagenles[i] = Rectangle(windows[i].bbox_.x, 35 | windows[i].bbox_.y, 36 | windows[i].bbox_.width, 37 | windows[i].bbox_.height); 38 | } 39 | 40 | extractor_->forwardPass(face_rectagenles, src, 1.f); 41 | 42 | auto keypoints = extractor_->getFaceKeypoints(); 43 | const int number_person = keypoints.getSize(0); 44 | const int number_keypoints = keypoints.getSize(1); 45 | const int dim = keypoints.getSize(2); 46 | result.resize(number_person); 47 | 48 | for(int person = 0; person < number_person; ++person){ 49 | for(int part = 0; part < number_keypoints; ++part){ 50 | result[person].points_.resize(number_keypoints); 51 | result[person].scores_.resize(number_keypoints); 52 | const auto face_idx = (person * number_keypoints + part) * dim; 53 | result[person].points_[part] = cv::Point2d(keypoints[face_idx], keypoints[face_idx+1]); 54 | result[person].scores_[part] = keypoints[face_idx + 2]; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | 61 | bool load_model(const std::vector& init_nets, 62 | const std::vector& predict_nets){ 63 | assert((init_nets.size() > 0) && (predict_nets.size() > 0)); 64 | pairs_ = FACE_PAIRS_RENDER; 65 | extractor_ = std::make_shared(Point(input_width_, input_height_), 66 | Point(input_width_, input_height_), 67 | init_nets[0], 68 | predict_nets[0], 69 | gpu_id_); 70 | 71 | extractor_->initializationOnThread(); 72 | return true; 73 | } 74 | 75 | private: 76 | std::shared_ptr extractor_; 77 | std::vector pairs_; 78 | int input_width_; 79 | int input_height_; 80 | int gpu_id_; 81 | 82 | 83 | 84 | DISABLE_COPY_AND_ASSIGN(OPFace); 85 | }; 86 | } 87 | } 88 | 89 | 90 | 91 | 92 | 93 | #endif //CL_FACE_FACE_POSE_H 94 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES 2 | cuda.cpp 3 | errorAndLog.cpp 4 | fileSystem.cpp 5 | flagsToOpenPose.cpp 6 | keypoint.cpp 7 | openCv.cpp 8 | profiler.cpp 9 | string.cpp) 10 | 11 | find_package(Boost COMPONENTS system filesystem REQUIRED) 12 | cuda_add_library(utilities ${SOURCES}) 13 | target_link_libraries(utilities ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) 14 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/check.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_CHECK_HPP 2 | #define OPENPOSE_UTILITIES_CHECK_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | // CHECK, CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, and CHECK_GT 9 | template 10 | void check(const bool condition, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 11 | { 12 | if (!condition) 13 | error("Check failed: " + tToString(message), line, function, file); 14 | } 15 | 16 | template 17 | void checkE(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 18 | { 19 | if (conditionA != conditionB) 20 | error("CheckE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 21 | } 22 | 23 | template 24 | void checkNE(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 25 | { 26 | if (conditionA == conditionB) 27 | error("CheckNE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 28 | } 29 | 30 | template 31 | void checkLE(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 32 | { 33 | if (conditionA > conditionB) 34 | error("CheckLE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 35 | } 36 | 37 | template 38 | void checkLT(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 39 | { 40 | if (conditionA >= conditionB) 41 | error("CheckLT failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 42 | } 43 | 44 | template 45 | void checkGE(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 46 | { 47 | if (conditionA < conditionB) 48 | error("CheckGE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 49 | } 50 | 51 | template 52 | void checkGT(const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, const std::string& function = "", const std::string& file = "") 53 | { 54 | if (conditionA <= conditionB) 55 | error("CheckGT failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + tToString(message), line, function, file); 56 | } 57 | } 58 | 59 | #endif // OPENPOSE_UTILITIES_CHECK_HPP 60 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace op 7 | { 8 | const dim3 THREADS_PER_BLOCK_TINY{32, 32, 1}; 9 | const dim3 THREADS_PER_BLOCK_SMALL{64, 64, 1}; 10 | const dim3 THREADS_PER_BLOCK_MEDIUM{128, 128, 1}; 11 | const dim3 THREADS_PER_BLOCK_BIG{256, 256, 1}; 12 | 13 | void cudaCheck(const int line, const std::string& function, const std::string& file) 14 | { 15 | const auto errorCode = cudaPeekAtLastError(); 16 | if(errorCode != cudaSuccess) 17 | error("Cuda check failed (" + std::to_string(errorCode) + " vs. " + std::to_string(cudaSuccess) + "): " + cudaGetErrorString(errorCode), line, function, file); 18 | } 19 | 20 | int getGpuNumber() 21 | { 22 | int gpuNumber; 23 | cudaGetDeviceCount(&gpuNumber); 24 | cudaCheck(__LINE__, __FUNCTION__, __FILE__); 25 | return gpuNumber; 26 | } 27 | 28 | dim3 getNumberCudaBlocks(const Point& frameSize, const dim3 numberCudaThreads) 29 | { 30 | try 31 | { 32 | return dim3{getNumberCudaBlocks((unsigned int)frameSize.x, numberCudaThreads.x), 33 | getNumberCudaBlocks((unsigned int)frameSize.y, numberCudaThreads.y), 34 | numberCudaThreads.z}; 35 | } 36 | catch (const std::exception& e) 37 | { 38 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 39 | return dim3{}; 40 | } 41 | } 42 | 43 | std::pair getNumberCudaThreadsAndBlocks(const Point& frameSize) 44 | { 45 | try 46 | { 47 | // Image <= 480p --> THREADS_PER_BLOCK_TINY 48 | // Image <= 720p --> THREADS_PER_BLOCK_SMALL 49 | // Image <= 16K --> THREADS_PER_BLOCK_MEDIUM 50 | // Image > 16K --> THREADS_PER_BLOCK_BIG 51 | const auto maxValue = fastMax(frameSize.x, frameSize.y); 52 | auto threadsPerBlock = THREADS_PER_BLOCK_TINY; 53 | if (maxValue >= 16384) 54 | threadsPerBlock = THREADS_PER_BLOCK_BIG; 55 | else if (maxValue > 1280) 56 | threadsPerBlock = THREADS_PER_BLOCK_MEDIUM; 57 | else if (maxValue > 640) 58 | threadsPerBlock = THREADS_PER_BLOCK_SMALL; 59 | return std::make_pair(threadsPerBlock, getNumberCudaBlocks(frameSize, threadsPerBlock)); 60 | } 61 | catch (const std::exception& e) 62 | { 63 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 64 | return std::make_pair(dim3{1,1,1}, dim3{1,1,1}); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/cuda.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_CUDA_HPP 2 | #define OPENPOSE_UTILITIES_CUDA_HPP 3 | 4 | #include // std::pair 5 | #include 6 | #include 7 | #include 8 | 9 | namespace op 10 | { 11 | const auto CUDA_NUM_THREADS = 512u; 12 | 13 | OP_API void cudaCheck(const int line = -1, const std::string& function = "", const std::string& file = ""); 14 | 15 | OP_API int getGpuNumber(); 16 | 17 | inline unsigned int getNumberCudaBlocks(const unsigned int totalRequired, const unsigned int numberCudaThreads = CUDA_NUM_THREADS) 18 | { 19 | return (totalRequired + numberCudaThreads - 1) / numberCudaThreads; 20 | } 21 | 22 | OP_API dim3 getNumberCudaBlocks(const Point& frameSize, const dim3 numberCudaThreads = dim3{ CUDA_NUM_THREADS, CUDA_NUM_THREADS, 1 }); 23 | 24 | OP_API std::pair getNumberCudaThreadsAndBlocks(const Point& frameSize); 25 | } 26 | 27 | #endif // OPENPOSE_UTILITIES_CUDA_HPP 28 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/enumClasses.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_ENUM_CLASSES_HPP 2 | #define OPENPOSE_UTILITIES_ENUM_CLASSES_HPP 3 | 4 | namespace op 5 | { 6 | enum class ErrorMode : unsigned char 7 | { 8 | StdRuntimeError, 9 | FileLogging, 10 | StdCerr, 11 | All, 12 | }; 13 | 14 | enum class LogMode : unsigned char 15 | { 16 | FileLogging, 17 | StdCout, 18 | All, 19 | }; 20 | 21 | enum class Priority : unsigned char 22 | { 23 | None = 0, 24 | Low = 1, 25 | Normal = 2, 26 | High = 3, 27 | Max = 4, 28 | NoOutput = 255, 29 | }; 30 | } 31 | 32 | #endif // OPENPOSE_UTILITIES_ENUM_CLASSES_HPP 33 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/errorAndLog.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP 2 | #define OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP 3 | 4 | #include 5 | #include 6 | #include // std::stringstream 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace op 13 | { 14 | template 15 | std::string tToString(const T& message) 16 | { 17 | // Message -> ostringstream 18 | std::ostringstream oss; 19 | oss << message; 20 | // ostringstream -> std::string 21 | return oss.str(); 22 | } 23 | 24 | // Error managment - How to use: 25 | // error(message, __LINE__, __FUNCTION__, __FILE__); 26 | OP_API void error(const std::string& message, const int line = -1, const std::string& function = "", const std::string& file = ""); 27 | 28 | template 29 | inline void error(const T& message, const int line = -1, const std::string& function = "", const std::string& file = "") 30 | { 31 | error(tToString(message), line, function, file); 32 | } 33 | 34 | // Printing info - How to use: 35 | // log(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__); // It will print info if desiredPriority >= sPriorityThreshold 36 | OP_API void log(const std::string& message, const Priority priority = Priority::Max, const int line = -1, const std::string& function = "", const std::string& file = ""); 37 | 38 | template 39 | inline void log(const T& message, const Priority priority = Priority::Max, const int line = -1, const std::string& function = "", const std::string& file = "") 40 | { 41 | log(tToString(message), priority, line, function, file); 42 | } 43 | 44 | // If only desired on debug mode (no computational cost at all on release mode): 45 | // dLog(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__); // It will print info if desiredPriority >= sPriorityThreshold 46 | template 47 | inline void dLog(const T& message, const Priority priority = Priority::Max, const int line = -1, const std::string& function = "", const std::string& file = "") 48 | { 49 | #ifndef NDEBUG 50 | log(message, priority, line, function, file); 51 | #else 52 | UNUSED(message); 53 | UNUSED(priority); 54 | UNUSED(line); 55 | UNUSED(function); 56 | UNUSED(file); 57 | #endif 58 | } 59 | 60 | // This class is thread-safe 61 | class OP_API ConfigureError 62 | { 63 | public: 64 | static std::vector getErrorModes(); 65 | 66 | static void setErrorModes(const std::vector& errorModes); 67 | }; 68 | 69 | // This class is thread-safe 70 | class OP_API ConfigureLog 71 | { 72 | public: 73 | static Priority getPriorityThreshold(); 74 | 75 | static const std::vector& getLogModes(); 76 | 77 | static void setPriorityThreshold(const Priority priorityThreshold); 78 | 79 | static void setLogModes(const std::vector& loggingModes); 80 | }; 81 | } 82 | 83 | #endif // OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP 84 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/fastMath.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_MATH_HPP 2 | #define OPENPOSE_UTILITIES_MATH_HPP 3 | 4 | namespace op 5 | { 6 | // Use op::round/max/min for basic types (int, char, long, float, double, etc). Never with classes! std:: alternatives uses 'const T&' instead of 'const T' as argument. 7 | // E.g. std::round is really slow (~300 ms vs ~10 ms when I individually apply it to each element of a whole image array (e.g. in floatPtrToUCharCvMat) 8 | 9 | // Round functions 10 | // Signed 11 | template 12 | inline char charRound(const T a) 13 | { 14 | return char(a+0.5f); 15 | } 16 | 17 | template 18 | inline signed char sCharRound(const T a) 19 | { 20 | return (signed char)(a+0.5f); 21 | } 22 | 23 | template 24 | inline int intRound(const T a) 25 | { 26 | return int(a+0.5f); 27 | } 28 | 29 | template 30 | inline long longRound(const T a) 31 | { 32 | return long(a+0.5f); 33 | } 34 | 35 | template 36 | inline long long longLongRound(const T a) 37 | { 38 | return (long long)(a+0.5f); 39 | } 40 | 41 | // Unsigned 42 | template 43 | inline unsigned char uCharRound(const T a) 44 | { 45 | return (unsigned char)(a+0.5f); 46 | } 47 | 48 | template 49 | inline unsigned int uIntRound(const T a) 50 | { 51 | return (unsigned int)(a+0.5f); 52 | } 53 | 54 | template 55 | inline unsigned long ulongRound(const T a) 56 | { 57 | return (unsigned long)(a+0.5f); 58 | } 59 | 60 | template 61 | inline unsigned long long uLongLongRound(const T a) 62 | { 63 | return (unsigned long long)(a+0.5f); 64 | } 65 | 66 | // Max/min functions 67 | template 68 | inline T fastMax(const T a, const T b) 69 | { 70 | return (a > b ? a : b); 71 | } 72 | 73 | template 74 | inline T fastMin(const T a, const T b) 75 | { 76 | return (a < b ? a : b); 77 | } 78 | 79 | template 80 | inline T fastTruncate(T value, T min = 0, T max = 1) 81 | { 82 | return fastMin(max, fastMax(min, value)); 83 | } 84 | } 85 | 86 | #endif // OPENPOSE_UTILITIES_MATH_HPP 87 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/fileSystem.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_FILE_SYSTEM_HPP 2 | #define OPENPOSE_UTILITIES_FILE_SYSTEM_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | OP_API void mkdir(const std::string& directoryPath); 9 | 10 | OP_API bool exist(const std::string& directoryPath); 11 | 12 | OP_API bool isDirectory(const std::string& directoryPath); 13 | 14 | /** 15 | * This function makes sure that the directoryPathString is properly formatted. I.e., it 16 | * changes all '\' by '/', and it makes sure that the string finishes with '/'. 17 | * @param directoryPathString std::string with the directory path to be formatted. 18 | * @return std::string with the formatted directory path. 19 | */ 20 | OP_API std::string formatAsDirectory(const std::string& directoryPathString); 21 | 22 | /** 23 | * This function extracts the file name and extension from a full path. 24 | * @param fullPath std::string with the full path. 25 | * @return std::string with the file name with extension. 26 | */ 27 | OP_API std::string getFileNameAndExtension(const std::string& fullPath); 28 | 29 | /** 30 | * This function extracts the file name (without extension) from a full path. 31 | * @param fullPath std::string with the full path. 32 | * @return std::string with the file name without extension. 33 | */ 34 | OP_API std::string getFileNameNoExtension(const std::string& fullPath); 35 | 36 | /** 37 | * This function extracts the extension from a full path. 38 | * @param fullPath std::string with the full path. 39 | * @return std::string with the file extension. 40 | */ 41 | OP_API std::string getFileExtension(const std::string& fullPath); 42 | 43 | /** 44 | * This function extracts all the files in a directory path with the desired 45 | * extensions. If no extensions is specified, then all the file names are returned. 46 | * @param directoryPath std::string with the directory path. 47 | * @param extensions std::vector with the extensions of the desired files. 48 | * @return std::vector with the existing file names. 49 | */ 50 | OP_API std::vector getFilesOnDirectory(const std::string& directoryPath, const std::vector& extensions = {}); 51 | 52 | /** 53 | * Analogous to getFilesOnDirectory(const std::string& directoryPath, const std::vector& extensions) for 1 specific 54 | * extension. 55 | * @param directoryPath std::string with the directory path. 56 | * @param extension std::string with the extension of the desired files. 57 | * @return std::vector with the existing file names. 58 | */ 59 | OP_API std::vector getFilesOnDirectory(const std::string& directoryPath, const std::string& extension); 60 | } 61 | 62 | #endif // OPENPOSE_UTILITIES_FILE_SYSTEM_HPP 63 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/flagsToOpenPose.cpp: -------------------------------------------------------------------------------- 1 | #include // sscanf 2 | #include 3 | #include 4 | 5 | namespace op 6 | { 7 | 8 | ScaleMode flagsToScaleMode(const int keypointScale) 9 | { 10 | try 11 | { 12 | log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); 13 | if (keypointScale == 0) 14 | return ScaleMode::InputResolution; 15 | else if (keypointScale == 1) 16 | return ScaleMode::NetOutputResolution; 17 | else if (keypointScale == 2) 18 | return ScaleMode::OutputResolution; 19 | else if (keypointScale == 3) 20 | return ScaleMode::ZeroToOne; 21 | else if (keypointScale == 4) 22 | return ScaleMode::PlusMinusOne; 23 | // else 24 | const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution," 25 | " NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; 26 | error(message, __LINE__, __FUNCTION__, __FILE__); 27 | return ScaleMode::InputResolution; 28 | } 29 | catch (const std::exception& e) 30 | { 31 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 32 | return ScaleMode::InputResolution; 33 | } 34 | } 35 | 36 | 37 | std::vector flagsToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs) 38 | { 39 | try 40 | { 41 | std::vector heatMapTypes; 42 | if (heatMapsAddParts) 43 | heatMapTypes.emplace_back(HeatMapType::Parts); 44 | if (heatMapsAddBkg) 45 | heatMapTypes.emplace_back(HeatMapType::Background); 46 | if (heatMapsAddPAFs) 47 | heatMapTypes.emplace_back(HeatMapType::PAFs); 48 | return heatMapTypes; 49 | } 50 | catch (const std::exception& e) 51 | { 52 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 53 | return {}; 54 | } 55 | } 56 | 57 | RenderMode flagsToRenderMode(const int renderFlag, const int renderPoseFlag) 58 | { 59 | try 60 | { 61 | if (renderFlag == -1 && renderPoseFlag != -2) 62 | return flagsToRenderMode(renderPoseFlag, -2); 63 | else if (renderFlag == 0) 64 | return RenderMode::None; 65 | else if (renderFlag == 1) 66 | return RenderMode::Cpu; 67 | else if (renderFlag == 2) 68 | return RenderMode::Gpu; 69 | // else 70 | error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__); 71 | return RenderMode::None; 72 | } 73 | catch (const std::exception& e) 74 | { 75 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 76 | return RenderMode::None; 77 | } 78 | } 79 | 80 | Point flagsToPoint(const std::string& pointString, const std::string& pointExample) 81 | { 82 | try 83 | { 84 | Point point; 85 | const auto nRead = sscanf(pointString.c_str(), "%dx%d", &point.x, &point.y); 86 | checkE(nRead, 2, "Invalid resolution format: `" + pointString + "`, it should be e.g. `" + pointExample 87 | + "`.", __LINE__, __FUNCTION__, __FILE__); 88 | return point; 89 | } 90 | catch (const std::exception& e) 91 | { 92 | error(e.what(), __LINE__, __FUNCTION__, __FILE__); 93 | return Point{}; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/flagsToOpenPose.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP 2 | #define OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace op 8 | { 9 | 10 | OP_API ScaleMode flagsToScaleMode(const int keypointScale); 11 | 12 | OP_API std::vector flagsToHeatMaps(const bool heatMapsAddParts = false, const bool heatMapsAddBkg = false, 13 | const bool heatMapsAddPAFs = false); 14 | 15 | OP_API RenderMode flagsToRenderMode(const int renderFlag, const int renderPoseFlag = -2); 16 | 17 | OP_API Point flagsToPoint(const std::string& pointString, const std::string& pointExample = "1280x720"); 18 | } 19 | 20 | #endif // OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP 21 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/headers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_HEADERS_HPP 2 | #define OPENPOSE_UTILITIES_HEADERS_HPP 3 | 4 | // utilities module 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #endif // OPENPOSE_UTILITIES_HEADERS_HPP 19 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/keypoint.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_KEYPOINT_HPP 2 | #define OPENPOSE_UTILITIES_KEYPOINT_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | OP_API float getDistance(const Array& keypoints, const int person, const int elementA, const int elementB); 9 | 10 | OP_API void averageKeypoints(Array& keypointsA, const Array& keypointsB, const int personA); 11 | 12 | OP_API void scaleKeypoints(Array& keypoints, const float scale); 13 | 14 | OP_API void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY); 15 | 16 | OP_API void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, 17 | const float offsetY); 18 | 19 | OP_API void renderKeypointsCpu(Array& frameArray, const Array& keypoints, 20 | const std::vector& pairs, const std::vector colors, 21 | const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle, 22 | const float threshold); 23 | 24 | OP_API Rectangle getKeypointsRectangle(const Array& keypoints, const int person, const int numberKeypoints, const float threshold); 25 | 26 | OP_API float getAverageScore(const Array& keypoints, const int person); 27 | 28 | OP_API float getKeypointsArea(const Array& keypoints, const int person, const int numberKeypoints, const float threshold); 29 | 30 | OP_API int getBiggestPerson(const Array& keypoints, const float threshold); 31 | } 32 | 33 | #endif // OPENPOSE_UTILITIES_KEYPOINT_HPP 34 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/openCv.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_OPEN_CV_HPP 2 | #define OPENPOSE_UTILITIES_OPEN_CV_HPP 3 | 4 | #include // cv::Mat 5 | #include // cv::warpAffine, cv::BORDER_CONSTANT 6 | #include 7 | 8 | namespace op 9 | { 10 | OP_API void putTextOnCvMat(cv::Mat& cvMat, const std::string& textToDisplay, const Point& position, const cv::Scalar& color, const bool normalizeWidth); 11 | 12 | OP_API void floatPtrToUCharCvMat(cv::Mat& uCharCvMat, const float* const floatPtrImage, const std::array resolutionSize); 13 | 14 | OP_API void unrollArrayToUCharCvMat(cv::Mat& cvMatResult, const Array& array); 15 | 16 | OP_API void uCharCvMatToFloatPtr(float* floatPtrImage, const cv::Mat& cvImage, const bool normalize); 17 | 18 | OP_API double resizeGetScaleFactor(const Point& initialSize, const Point& targetSize); 19 | 20 | OP_API cv::Mat resizeFixedAspectRatio(const cv::Mat& cvMat, const double scaleFactor, const Point& targetSize, const int borderMode = cv::BORDER_CONSTANT, 21 | const cv::Scalar& borderValue = cv::Scalar{0,0,0}); 22 | } 23 | 24 | #endif // OPENPOSE_UTILITIES_OPEN_CV_HPP 25 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/pointerContainer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP 2 | #define OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP 3 | 4 | namespace op 5 | { 6 | template 7 | inline bool checkNoNullNorEmpty(const TPointerContainer& tPointerContainer) 8 | { 9 | return (tPointerContainer != nullptr && tPointerContainer->size() > 0); 10 | } 11 | 12 | template 13 | class PointerContainerGreater 14 | { 15 | public: 16 | bool operator() (TDatums& a, TDatums& b) 17 | { 18 | if (!b || b->empty()) 19 | return true; 20 | else if (!a || a->empty()) 21 | return false; 22 | else 23 | return (*a)[0] > (*b)[0]; 24 | } 25 | }; 26 | 27 | template 28 | class PointerContainerLess 29 | { 30 | public: 31 | bool operator() (TDatums& a, TDatums& b) 32 | { 33 | if (!b || b->empty()) 34 | return false; 35 | else if (!a || a->empty()) 36 | return true; 37 | else 38 | return (*a)[0] < (*b)[0]; 39 | } 40 | }; 41 | } 42 | 43 | #endif // OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP 44 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/profiler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_PROFILER_HPP 2 | #define OPENPOSE_UTILITIES_PROFILER_HPP 3 | 4 | #include 5 | //#include 6 | 7 | // Enable PROFILER_ENABLED on Makefile.config in order to use this function. Otherwise nothing will be outputted. 8 | 9 | // How to use - example: 10 | // For GPU - It can only be applied in the main.cpp file: 11 | // Profiler::profileGpuMemory(__LINE__, __FUNCTION__, __FILE__); 12 | // For time: 13 | // // ... inside continuous loop ... 14 | // const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); 15 | // // functions to do... 16 | // Profiler::timerEnd(profilerKey); 17 | // Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X); 18 | 19 | namespace op 20 | { 21 | class OP_API Profiler 22 | { 23 | public: 24 | static const unsigned long long DEFAULT_X; 25 | 26 | static const std::string timerInit(const int line, const std::string& function, const std::string& file); 27 | 28 | static void timerEnd(const std::string& key); 29 | 30 | static void printAveragedTimeMsOnIterationX(const std::string& key, const int line, const std::string& function, const std::string& file, const unsigned long long x = DEFAULT_X); 31 | 32 | static void printAveragedTimeMsEveryXIterations(const std::string& key, const int line, const std::string& function, const std::string& file, const unsigned long long x = DEFAULT_X); 33 | 34 | static void profileGpuMemory(const int line, const std::string& function, const std::string& file); 35 | }; 36 | } 37 | 38 | #endif // OPENPOSE_UTILITIES_PROFILER_HPP 39 | -------------------------------------------------------------------------------- /cpp_modules/openpose/utilities/string.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPENPOSE_UTILITIES_STRING_HPP 2 | #define OPENPOSE_UTILITIES_STRING_HPP 3 | 4 | #include 5 | 6 | namespace op 7 | { 8 | OP_API unsigned long long getLastNumber(const std::string& string); 9 | 10 | /** 11 | * This template function turns an integer number into a fixed-length std::string. 12 | * @param number T integer corresponding to the integer to be formatted. 13 | * @param stringLength unsigned long long indicating the final length. If 0, the 14 | * final length is the original number length. 15 | * @return std::string with the formatted value. 16 | */ 17 | template 18 | OP_API std::string toFixedLengthString(const T number, const unsigned long long stringLength = 0); 19 | 20 | OP_API std::vector splitString(const std::string& stringToSplit, const std::string& delimiter); 21 | 22 | OP_API std::string toLower(const std::string& string); 23 | 24 | OP_API std::string toUpper(const std::string& string); 25 | } 26 | 27 | #endif // OPENPOSE_UTILITIES_STRING_HPP 28 | -------------------------------------------------------------------------------- /cpp_modules/recognition/include/net_caffe.h: -------------------------------------------------------------------------------- 1 | #ifndef CL_FACE_NET_CAFFE_H 2 | #define CL_FACE_NET_CAFFE_H 3 | 4 | #include 5 | #include // std::shared_ptr 6 | #include 7 | #include 8 | #include 9 | #include "cl_common.h" 10 | 11 | namespace cl 12 | { 13 | class NetCaffe 14 | { 15 | public: 16 | NetCaffe(const std::string& init_net, 17 | const std::string& predict_net, 18 | const std::string& layer_name = "embedding", 19 | const int gpu_id = 0); 20 | 21 | virtual ~NetCaffe(){} 22 | 23 | bool init(int batch_size, int channels, int height, int width); 24 | void forward_pass(const float* const input_data = nullptr) const; 25 | void extract_feature(const int src_image_num, std::vector>& features) const; 26 | 27 | std::vector extract_feature() const 28 | { 29 | const float* embedding = output_->cpu_data(); 30 | int step = output_->num(); 31 | std::vector feature(embedding, embedding + step*output_->channels()); 32 | return feature; 33 | } 34 | 35 | 36 | private: 37 | 38 | const int gpu_id_; 39 | const std::string init_net_; 40 | const std::string predict_net_; 41 | const std::string layer_name_; 42 | 43 | unsigned long input_memory_; 44 | 45 | std::unique_ptr> net_; 46 | boost::shared_ptr> output_; 47 | 48 | DISABLE_COPY_AND_ASSIGN(NetCaffe); 49 | }; 50 | } 51 | 52 | #endif // CL_FACE_NET_CAFFE_H 53 | -------------------------------------------------------------------------------- /cpp_modules/recognition/include/sphereface/sphereface.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-8-29. 3 | // 4 | #ifndef CL_FACE_SPHEREFACE_H 5 | #define CL_FACE_SPHEREFACE_H 6 | 7 | #include "cl_recognizer.h" 8 | #include "net_caffe.h" 9 | 10 | namespace sf{ 11 | namespace fr{ 12 | class SphereFace: public cl::fr::Recognizer{ 13 | public: 14 | explicit SphereFace(int batch_size = 1, int channels = 3, int height = 112, int width = 96, bool do_flip = false); 15 | ~SphereFace(){} 16 | 17 | virtual int extract_feature_or_identify(const std::vector& face_images, 18 | const std::vector& face_windows, 19 | const std::vector>& face_landmarks, 20 | std::vector>& features); 21 | 22 | std::vector extract_feature(cv::Mat& aligned_face); 23 | 24 | virtual bool load_model(const std::vector& init_nets, 25 | const std::vector& predict_nets); 26 | 27 | private: 28 | void preprocess(const cv::Mat& src, 29 | const std::vector& landmarks, 30 | std::vector&blob_data); 31 | private: 32 | int batch_size_; 33 | int channels_; 34 | int height_; 35 | int width_; 36 | bool do_flip_; 37 | bool do_ensemble_; 38 | std::shared_ptr sphere20_; 39 | 40 | DISABLE_COPY_AND_ASSIGN(SphereFace); 41 | }; 42 | 43 | } 44 | 45 | } 46 | 47 | 48 | #endif //CL_FACE_SPHEREFACE_H 49 | -------------------------------------------------------------------------------- /cpp_modules/recognition/src/net_caffe.cpp: -------------------------------------------------------------------------------- 1 | #include "net_caffe.h" 2 | 3 | #include // std::accumulate 4 | #include 5 | #include 6 | 7 | 8 | namespace cl 9 | { 10 | using namespace cv; 11 | using namespace std; 12 | 13 | NetCaffe::NetCaffe(const std::string& init_net, 14 | const std::string& predict_net, 15 | const std::string& layer_name, 16 | const int gpu_id): 17 | gpu_id_{gpu_id}, 18 | init_net_{init_net}, 19 | predict_net_{predict_net}, 20 | layer_name_{layer_name} 21 | { 22 | } 23 | 24 | bool NetCaffe::init(int batch_size, int channels, int height, int width) 25 | { 26 | input_memory_ = batch_size*channels*height*width*sizeof(float); 27 | caffe::Caffe::set_mode(caffe::Caffe::GPU); 28 | caffe::Caffe::SetDevice(gpu_id_); 29 | net_.reset(new caffe::Net{init_net_, caffe::TEST}); 30 | net_->CopyTrainedLayersFrom(predict_net_); 31 | net_->blobs()[0]->Reshape({batch_size, channels, height, width}); 32 | net_->Reshape(); 33 | output_ = net_->blob_by_name(layer_name_); 34 | return true; 35 | } 36 | 37 | 38 | void NetCaffe::forward_pass(const float* const input_data) const 39 | { 40 | if (input_data != nullptr) 41 | { 42 | auto* input_data_gpu = net_->blobs().at(0)->mutable_gpu_data(); 43 | cudaMemcpy(input_data_gpu, input_data, input_memory_, cudaMemcpyHostToDevice); 44 | } 45 | net_->ForwardFrom(0); 46 | } 47 | 48 | void NetCaffe::extract_feature(const int src_image_num, std::vector>& features) const 49 | { 50 | const float* embedding = output_->cpu_data(); 51 | features.resize(src_image_num); 52 | int step = output_->num()/src_image_num; 53 | int offset = 0; 54 | for(int i = 0; i < src_image_num; ++i){ 55 | features[i] = vector(embedding + offset, embedding + offset + step*output_->channels()); 56 | offset += step*output_->channels(); 57 | } 58 | } 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /cpp_modules/recognition/src/sphereface/sphereface.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-8-29. 3 | // 4 | 5 | #include "sphereface.h" 6 | 7 | using namespace std; 8 | using namespace cv; 9 | 10 | namespace sf{ 11 | namespace fr{ 12 | SphereFace::SphereFace(int batch_size, 13 | int channels, 14 | int height, 15 | int width, 16 | bool do_flip):batch_size_(batch_size), channels_(channels), height_(height), width_(width),do_flip_(do_flip) 17 | { 18 | if(do_flip_) 19 | { 20 | batch_size_ = 2*batch_size; 21 | } 22 | } 23 | 24 | int SphereFace::extract_feature_or_identify(const std::vector& face_images, 25 | const std::vector& face_windows, 26 | const std::vector>& face_landmarks, 27 | std::vector>& features) { 28 | assert(face_windows.size() == face_landmarks.size()); 29 | vector input_blob; 30 | for(size_t i = 0; i < face_images.size(); ++i){ 31 | if(face_windows.size() == 0){ 32 | do_ensemble_ = false; 33 | } 34 | this->preprocess(face_images[i], face_landmarks[i], input_blob); 35 | } 36 | sphere20_->forward_pass(input_blob.data()); 37 | int src_image_num = face_images.size(); 38 | sphere20_->extract_feature(src_image_num, features); 39 | } 40 | 41 | vector SphereFace::extract_feature(cv::Mat& aligned_face){ 42 | vector input_blob; 43 | preprocess(aligned_face, {}, input_blob); 44 | sphere20_->forward_pass(input_blob.data()); 45 | return sphere20_->extract_feature(); 46 | 47 | } 48 | 49 | void SphereFace::preprocess(const cv::Mat& src, 50 | const std::vector& landmarks, 51 | std::vector&blob_data){ 52 | 53 | //resize 54 | Mat image = src.clone(); 55 | image.convertTo(image, CV_32FC3, 1.0/128, -127.5/128); 56 | 57 | //NHWC to NCHW 58 | vector channels(3); 59 | cv::split(image, channels); 60 | for (auto &c : channels) { 61 | blob_data.insert(blob_data.end(), (float *)c.datastart, (float *)c.dataend); 62 | } 63 | 64 | 65 | if(do_flip_){ 66 | Mat image_flip; 67 | flip(image, image_flip, 0); 68 | vector channels_flip(3); 69 | cv::split(image_flip, channels_flip); 70 | for (auto &c : channels_flip) { 71 | blob_data.insert(blob_data.end(), (float *)c.datastart, (float *)c.dataend); 72 | } 73 | } 74 | } 75 | 76 | 77 | bool SphereFace::load_model(const std::vector& init_nets, 78 | const std::vector& predict_nets){ 79 | 80 | sphere20_ = std::make_shared(init_nets[0], predict_nets[0], "fc5"); 81 | return sphere20_->init(batch_size_, channels_, height_, width_); 82 | } 83 | 84 | 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /cpp_modules/tracking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES tracker.cpp) 2 | add_library(tracker ${SOURCES}) 3 | target_link_libraries(tracker alignment_lib ${OpenCV_LIBS}) 4 | -------------------------------------------------------------------------------- /cpp_modules/tracking/tracker.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-26. 3 | // 4 | #include "tracker.hpp" 5 | #include "openpose/face/faceParameters.hpp" 6 | 7 | using namespace cl::ft; 8 | using namespace cv; 9 | using namespace std; 10 | 11 | Tracker::Tracker(const string& pdm_model, 12 | const float render_threshold, 13 | cl::fa::Alignment* alignment) { 14 | pdm_.Read(pdm_model); 15 | face_alignment_.reset(alignment); 16 | render_threshold_ = render_threshold; 17 | params_local_.create(pdm_.NumberOfModes(), 1); 18 | reset(); 19 | } 20 | 21 | 22 | bool Tracker::check_landmarks(const cl::FaceLandmark& landmarks){ 23 | 24 | return true; 25 | } 26 | 27 | 28 | void Tracker::update_template(const cv::Mat& bgr_image){ 29 | auto bbox = compute_bbox() & cv::Rect(0, 0, bgr_image.cols, bgr_image.rows); 30 | face_template_ = bgr_image(bbox).clone(); 31 | } 32 | 33 | 34 | void Tracker::match_template(const cv::Mat& bgr_image){ 35 | 36 | double scaling = param_.face_template_scale_; 37 | cv::Mat image; 38 | // if(scaling < 1) 39 | // { 40 | // cv::resize(face_template_, face_template_, cv::Size(), scaling, scaling); 41 | // cv::resize(bgr_image, image, cv::Size(), scaling, scaling); 42 | // } 43 | // else 44 | { 45 | scaling = 1; 46 | image = bgr_image.clone(); 47 | } 48 | 49 | // Resizing the template 50 | cv::Mat corr_out; 51 | cv::Mat image_gray, face_template_gray; 52 | 53 | cv::cvtColor(image, image_gray, CV_BGR2BGRA); 54 | cv::cvtColor(face_template_, face_template_gray, CV_BGR2BGRA); 55 | cv::matchTemplate(image_gray, face_template_gray, corr_out, CV_TM_CCOEFF_NORMED); 56 | 57 | // Actually matching it 58 | //double min, max; 59 | int max_loc[2]; 60 | cv::minMaxIdx(corr_out, NULL, NULL, NULL, max_loc); 61 | 62 | cv::Rect out_bbox(max_loc[1]/scaling, 63 | max_loc[0]/scaling, 64 | face_template_.rows / scaling, 65 | face_template_.cols / scaling); 66 | 67 | face_rect_ = out_bbox & cv::Rect(0, 0, bgr_image.cols, bgr_image.rows); 68 | } 69 | 70 | 71 | void Tracker::reset(){ 72 | param_.use_face_template_ = true; 73 | param_.face_template_scale_ = 1.f; 74 | tracking_success_ = false; 75 | initialised_ = false; 76 | params_local_.setTo(0.0); 77 | params_global_ = cv::Vec6d(1, 0, 0, 0, 0, 0); 78 | failures_ = -1; 79 | face_template_ = cv::Mat(); 80 | face_rect_ = cv::Rect(); 81 | } 82 | 83 | 84 | bool Tracker::tracking(const cv::Mat& bgr_image, const cv::Rect& bouding_box) { 85 | 86 | if(!initialised_ && bouding_box.width > 0){ 87 | face_rect_ = bouding_box & cv::Rect(0, 0, bgr_image.cols, bgr_image.rows) ; 88 | initialised_ = true; 89 | } 90 | 91 | if(initialised_) { 92 | if(param_.use_face_template_ && !face_template_.empty() && tracking_success_){ 93 | match_template(bgr_image); 94 | } 95 | 96 | cl::FaceBox window(face_rect_); 97 | result_.resize(1); 98 | tracking_success_ = face_alignment_->detect(bgr_image, { window }, result_); 99 | 100 | if(!check_landmarks(result_[0])){ 101 | failures_++; 102 | } else{ 103 | failures_--; 104 | update_template(bgr_image); 105 | } 106 | return tracking_success_; 107 | 108 | } else { 109 | return false; 110 | } 111 | } 112 | 113 | 114 | 115 | void Tracker::draw(cv::Mat& display_img) { 116 | 117 | int thickness = (int)std::ceil(3.0* ((double)display_img.cols) / 640.0); 118 | int thickness_2 = (int)std::ceil(1.0* ((double)display_img.cols) / 640.0); 119 | if(!face_rect_.empty()) 120 | cv::rectangle(display_img, face_rect_, cv::Scalar(0, 255, 0), thickness); 121 | 122 | if(!result_.empty()) 123 | for(auto& e: result_[0].points_){ 124 | cv::circle(display_img, Point(e.x, e.y), 1 * DrawMultiplier, cv::Scalar(0, 0, 255), thickness, CV_AA, DrawShiftbits); 125 | cv::circle(display_img, Point(e.x, e.y), 1 * DrawMultiplier, cv::Scalar(255, 0, 0), thickness_2, CV_AA, DrawShiftbits); 126 | } 127 | } -------------------------------------------------------------------------------- /cpp_modules/tracking/tracker.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by root on 17-9-26. 3 | // 4 | 5 | #ifndef CL_FACE_FLOW_TRACKER_H 6 | #define CL_FACE_FLOW_TRACKER_H 7 | 8 | #include "cl_common.h" 9 | #include "cl_alignment.h" 10 | #include "PDM.h" 11 | 12 | #include 13 | 14 | namespace cl{ 15 | namespace ft{ 16 | 17 | class Tracker{ 18 | public: 19 | Tracker(const string& pdm_model, 20 | const float render_threshold = 0.4, 21 | cl::fa::Alignment* alignment = nullptr); 22 | virtual ~Tracker(){} 23 | 24 | bool tracking(const cv::Mat& bgr_image, const cv::Rect& bouding_box = {}); 25 | void reset(); 26 | 27 | cv::Rect get_bbox() { return face_rect_;} 28 | 29 | void draw(cv::Mat& display_img); 30 | 31 | struct Param{ 32 | float face_template_scale_; 33 | bool use_face_template_; 34 | }; 35 | 36 | private: 37 | void match_template(const cv::Mat& bgr_image); 38 | void update_template(const cv::Mat& bgr_image); 39 | bool check_landmarks(const cl::FaceLandmark& landmarks); 40 | 41 | cv::Rect compute_bbox() const { 42 | return cv::boundingRect(result_[0].points_); 43 | } 44 | 45 | 46 | public: 47 | int failures_; 48 | bool tracking_success_; 49 | private: 50 | cv::Mat face_template_; 51 | cv::Rect face_rect_; 52 | bool initialised_; 53 | float render_threshold_; 54 | Param param_; 55 | LandmarkDetector::PDM pdm_; 56 | cv::Mat_ params_local_; 57 | cv::Vec6d params_global_; 58 | std::shared_ptr face_alignment_; 59 | vector result_; 60 | const int DrawShiftbits = 0; 61 | const int DrawMultiplier = 2; 62 | 63 | DISABLE_COPY_AND_ASSIGN(Tracker); 64 | }; 65 | 66 | } 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | #endif //CL_FACE_FLOW_TRACKER_H 81 | -------------------------------------------------------------------------------- /result/aligned.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/result/aligned.jpg -------------------------------------------------------------------------------- /result/all.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/result/all.gif -------------------------------------------------------------------------------- /result/thumbnail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/result/thumbnail.jpg -------------------------------------------------------------------------------- /trained_models/detection/det1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/trained_models/detection/det1.caffemodel -------------------------------------------------------------------------------- /trained_models/detection/det1.prototxt: -------------------------------------------------------------------------------- 1 | name: "PNet" 2 | input: "data" 3 | input_dim: 1 4 | input_dim: 3 5 | input_dim: 12 6 | input_dim: 12 7 | 8 | layer { 9 | name: "conv1" 10 | type: "Convolution" 11 | bottom: "data" 12 | top: "conv1" 13 | param { 14 | lr_mult: 1 15 | decay_mult: 1 16 | } 17 | param { 18 | lr_mult: 2 19 | decay_mult: 0 20 | } 21 | convolution_param { 22 | num_output: 10 23 | kernel_size: 3 24 | stride: 1 25 | weight_filler { 26 | type: "xavier" 27 | } 28 | bias_filler { 29 | type: "constant" 30 | value: 0 31 | } 32 | } 33 | } 34 | layer { 35 | name: "PReLU1" 36 | type: "PReLU" 37 | bottom: "conv1" 38 | top: "conv1" 39 | } 40 | layer { 41 | name: "pool1" 42 | type: "Pooling" 43 | bottom: "conv1" 44 | top: "pool1" 45 | pooling_param { 46 | pool: MAX 47 | kernel_size: 2 48 | stride: 2 49 | } 50 | } 51 | 52 | layer { 53 | name: "conv2" 54 | type: "Convolution" 55 | bottom: "pool1" 56 | top: "conv2" 57 | param { 58 | lr_mult: 1 59 | decay_mult: 1 60 | } 61 | param { 62 | lr_mult: 2 63 | decay_mult: 0 64 | } 65 | convolution_param { 66 | num_output: 16 67 | kernel_size: 3 68 | stride: 1 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | value: 0 75 | } 76 | } 77 | } 78 | layer { 79 | name: "PReLU2" 80 | type: "PReLU" 81 | bottom: "conv2" 82 | top: "conv2" 83 | } 84 | 85 | layer { 86 | name: "conv3" 87 | type: "Convolution" 88 | bottom: "conv2" 89 | top: "conv3" 90 | param { 91 | lr_mult: 1 92 | decay_mult: 1 93 | } 94 | param { 95 | lr_mult: 2 96 | decay_mult: 0 97 | } 98 | convolution_param { 99 | num_output: 32 100 | kernel_size: 3 101 | stride: 1 102 | weight_filler { 103 | type: "xavier" 104 | } 105 | bias_filler { 106 | type: "constant" 107 | value: 0 108 | } 109 | } 110 | } 111 | layer { 112 | name: "PReLU3" 113 | type: "PReLU" 114 | bottom: "conv3" 115 | top: "conv3" 116 | } 117 | 118 | 119 | layer { 120 | name: "conv4-1" 121 | type: "Convolution" 122 | bottom: "conv3" 123 | top: "conv4-1" 124 | param { 125 | lr_mult: 1 126 | decay_mult: 1 127 | } 128 | param { 129 | lr_mult: 2 130 | decay_mult: 0 131 | } 132 | convolution_param { 133 | num_output: 2 134 | kernel_size: 1 135 | stride: 1 136 | weight_filler { 137 | type: "xavier" 138 | } 139 | bias_filler { 140 | type: "constant" 141 | value: 0 142 | } 143 | } 144 | } 145 | 146 | layer { 147 | name: "conv4-2" 148 | type: "Convolution" 149 | bottom: "conv3" 150 | top: "conv4-2" 151 | param { 152 | lr_mult: 1 153 | decay_mult: 1 154 | } 155 | param { 156 | lr_mult: 2 157 | decay_mult: 0 158 | } 159 | convolution_param { 160 | num_output: 4 161 | kernel_size: 1 162 | stride: 1 163 | weight_filler { 164 | type: "xavier" 165 | } 166 | bias_filler { 167 | type: "constant" 168 | value: 0 169 | } 170 | } 171 | } 172 | layer { 173 | name: "prob1" 174 | type: "Softmax" 175 | bottom: "conv4-1" 176 | top: "prob1" 177 | } 178 | -------------------------------------------------------------------------------- /trained_models/detection/det2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/trained_models/detection/det2.caffemodel -------------------------------------------------------------------------------- /trained_models/detection/det2.prototxt: -------------------------------------------------------------------------------- 1 | name: "RNet" 2 | input: "data" 3 | input_dim: 1 4 | input_dim: 3 5 | input_dim: 24 6 | input_dim: 24 7 | 8 | layer { 9 | name: "conv1" 10 | type: "Convolution" 11 | bottom: "data" 12 | top: "conv1" 13 | param { 14 | lr_mult: 0 15 | decay_mult: 0 16 | } 17 | param { 18 | lr_mult: 0 19 | decay_mult: 0 20 | } 21 | convolution_param { 22 | num_output: 28 23 | kernel_size: 3 24 | stride: 1 25 | weight_filler { 26 | type: "xavier" 27 | } 28 | bias_filler { 29 | type: "constant" 30 | value: 0 31 | } 32 | } 33 | } 34 | layer { 35 | name: "prelu1" 36 | type: "PReLU" 37 | bottom: "conv1" 38 | top: "conv1" 39 | propagate_down: true 40 | } 41 | layer { 42 | name: "pool1" 43 | type: "Pooling" 44 | bottom: "conv1" 45 | top: "pool1" 46 | pooling_param { 47 | pool: MAX 48 | kernel_size: 3 49 | stride: 2 50 | } 51 | } 52 | 53 | layer { 54 | name: "conv2" 55 | type: "Convolution" 56 | bottom: "pool1" 57 | top: "conv2" 58 | param { 59 | lr_mult: 0 60 | decay_mult: 0 61 | } 62 | param { 63 | lr_mult: 0 64 | decay_mult: 0 65 | } 66 | convolution_param { 67 | num_output: 48 68 | kernel_size: 3 69 | stride: 1 70 | weight_filler { 71 | type: "xavier" 72 | } 73 | bias_filler { 74 | type: "constant" 75 | value: 0 76 | } 77 | } 78 | } 79 | layer { 80 | name: "prelu2" 81 | type: "PReLU" 82 | bottom: "conv2" 83 | top: "conv2" 84 | propagate_down: true 85 | } 86 | layer { 87 | name: "pool2" 88 | type: "Pooling" 89 | bottom: "conv2" 90 | top: "pool2" 91 | pooling_param { 92 | pool: MAX 93 | kernel_size: 3 94 | stride: 2 95 | } 96 | } 97 | #################################### 98 | 99 | ################################## 100 | layer { 101 | name: "conv3" 102 | type: "Convolution" 103 | bottom: "pool2" 104 | top: "conv3" 105 | param { 106 | lr_mult: 0 107 | decay_mult: 0 108 | } 109 | param { 110 | lr_mult: 0 111 | decay_mult: 0 112 | } 113 | convolution_param { 114 | num_output: 64 115 | kernel_size: 2 116 | stride: 1 117 | weight_filler { 118 | type: "xavier" 119 | } 120 | bias_filler { 121 | type: "constant" 122 | value: 0 123 | } 124 | } 125 | } 126 | layer { 127 | name: "prelu3" 128 | type: "PReLU" 129 | bottom: "conv3" 130 | top: "conv3" 131 | propagate_down: true 132 | } 133 | ############################### 134 | 135 | ############################### 136 | 137 | layer { 138 | name: "conv4" 139 | type: "InnerProduct" 140 | bottom: "conv3" 141 | top: "conv4" 142 | param { 143 | lr_mult: 0 144 | decay_mult: 0 145 | } 146 | param { 147 | lr_mult: 0 148 | decay_mult: 0 149 | } 150 | inner_product_param { 151 | num_output: 128 152 | weight_filler { 153 | type: "xavier" 154 | } 155 | bias_filler { 156 | type: "constant" 157 | value: 0 158 | } 159 | } 160 | } 161 | layer { 162 | name: "prelu4" 163 | type: "PReLU" 164 | bottom: "conv4" 165 | top: "conv4" 166 | } 167 | 168 | layer { 169 | name: "conv5-1" 170 | type: "InnerProduct" 171 | bottom: "conv4" 172 | top: "conv5-1" 173 | param { 174 | lr_mult: 0 175 | decay_mult: 0 176 | } 177 | param { 178 | lr_mult: 0 179 | decay_mult: 0 180 | } 181 | inner_product_param { 182 | num_output: 2 183 | #kernel_size: 1 184 | #stride: 1 185 | weight_filler { 186 | type: "xavier" 187 | } 188 | bias_filler { 189 | type: "constant" 190 | value: 0 191 | } 192 | } 193 | } 194 | layer { 195 | name: "conv5-2" 196 | type: "InnerProduct" 197 | bottom: "conv4" 198 | top: "conv5-2" 199 | param { 200 | lr_mult: 1 201 | decay_mult: 1 202 | } 203 | param { 204 | lr_mult: 2 205 | decay_mult: 1 206 | } 207 | inner_product_param { 208 | num_output: 4 209 | #kernel_size: 1 210 | #stride: 1 211 | weight_filler { 212 | type: "xavier" 213 | } 214 | bias_filler { 215 | type: "constant" 216 | value: 0 217 | } 218 | } 219 | } 220 | layer { 221 | name: "prob1" 222 | type: "Softmax" 223 | bottom: "conv5-1" 224 | top: "prob1" 225 | } -------------------------------------------------------------------------------- /trained_models/detection/det3-half.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/trained_models/detection/det3-half.caffemodel -------------------------------------------------------------------------------- /trained_models/detection/det3.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpys/face-everthing/74466b9fe5d379439e08bc85ebe9f010fc2f5be7/trained_models/detection/det3.caffemodel --------------------------------------------------------------------------------