OpenCV
4.10.0
Open Source Computer Vision
|
In this tutorial you will learn how to:
Add the class header
The class header for a new algorithm should be added to a new file in include/opencv2/face. Here is the template that you can use to integrate a new algorithm, change the FacemarkNEW to a representative name of the new algorithm and save it using a representative filename accordingly.
@code{.cpp} class CV_EXPORTS_W FacemarkNEW : public Facemark { public: struct CV_EXPORTS Config { Config(); /*read only parameters - just for example*/ double detect_thresh; //!< detection confidence threshold double sigma; //!< another parameter void read(const FileNode& /*fn*/); void write(FileStorage& /*fs*/) const; }; /*Builder and destructor*/ static Ptr<FacemarkNEW> create(const FacemarkNEW::Config &conf = FacemarkNEW::Config() ); virtual ~FacemarkNEW(){}; }; @endcode
Add the implementation code
Create a new file in the source folder with name representing the new algorithm. Here is the template that you can use.
@code{.cpp} #include "opencv2/face.hpp" #include "precomp.hpp" namespace cv { FacemarkNEW::Config::Config(){ detect_thresh = 0.5; sigma=0.2; } void FacemarkNEW::Config::read( const cv::FileNode& fn ){ *this = FacemarkNEW::Config(); if (!fn["detect_thresh"].empty()) fn["detect_thresh"] >> detect_thresh; if (!fn["sigma"].empty()) fn["sigma"] >> sigma; } void FacemarkNEW::Config::write( cv::FileStorage& fs ) const{ fs << "detect_thresh" << detect_thresh; fs << "sigma" << sigma; } /*implementation of the algorithm is in this class*/ class FacemarkNEWImpl : public FacemarkNEW { public: FacemarkNEWImpl( const FacemarkNEW::Config &conf = FacemarkNEW::Config() ); void read( const FileNode& /*fn*/ ); void write( FileStorage& /*fs*/ ) const; void loadModel(String filename); bool setFaceDetector(bool(*f)(InputArray , OutputArray, void * extra_params)); bool getFaces( InputArray image , OutputArray faces, void * extra_params); Config config; protected: bool addTrainingSample(InputArray image, InputArray landmarks); void training(); bool fit(InputArray image, InputArray faces, InputOutputArray landmarks, void * runtime_params); Config config; // configurations /*proxy to the user defined face detector function*/ bool(*faceDetector)(InputArray , OutputArray, void * ); }; // class Ptr<FacemarkNEW> FacemarkNEW::create(const FacemarkNEW::Config &conf){ return Ptr<FacemarkNEWImpl>(new FacemarkNEWImpl(conf)); } FacemarkNEWImpl::FacemarkNEWImpl( const FacemarkNEW::Config &conf ) : config( conf ) { // other initialization } bool FacemarkNEWImpl::addTrainingSample(InputArray image, InputArray landmarks){ // pre-process and save the new training sample return true; } void FacemarkNEWImpl::training(){ printf("training\n"); } bool FacemarkNEWImpl::fit( InputArray image, InputArray faces, InputOutputArray landmarks, void * runtime_params) { if(runtime_params!=0){ // do something based on the extra parameters } printf("fitting\n"); return 0; } void FacemarkNEWImpl::read( const cv::FileNode& fn ){ config.read( fn ); } void FacemarkNEWImpl::write( cv::FileStorage& fs ) const { config.write( fs ); } void FacemarkNEWImpl::loadModel(String filename){ // load the model } bool FacemarkNEWImpl::setFaceDetector(bool(*f)(InputArray , OutputArray, void * extra_params )){ faceDetector = f; isSetDetector = true; return true; } bool FacemarkNEWImpl::getFaces( InputArray image , OutputArray roi, void * extra_params){ if(!isSetDetector){ return false; } if(extra_params!=0){ //extract the extra parameters } std::vector<Rect> & faces = *(std::vector<Rect>*)roi.getObj(); faces.clear(); faceDetector(image.getMat(), faces, extra_params); return true; } } @endcode
Compiling the code
Clear the build folder and then rebuild the entire library. Note that you can deactivate the compilation of other contrib modules by adding "-D BUILD_opencv_<MODULE_NAME>=OFF" flag to the cmake. After that you can execute make command in "<build_folder>/modules/face" to speed up the compiling process.
Handling the extra parameters To handle the extra parameters, a new struct should be created to holds all the required parameters. Here is an example of of a parameters container
Here is a snippet to extract the extra parameters:
And here is an example to pass the extra parameter into fit function
In order to understand this scheme, here is a simple example that you can try to compile and see how it works.
imgcodecs
and highgui
.