Goals
In this tutorial you will learn how to:
- integrate a new algorithm of facial landmark detector into the Facemark API
- compile a specific contrib module
- using extra parameters in a function
Explanation
public:
struct CV_EXPORTS Config {
Config();
double detect_thresh;
double sigma;
void read(
const FileNode& );
void write(FileStorage& )
const;
};
static Ptr<FacemarkNEW> create(const FacemarkNEW::Config &conf = FacemarkNEW::Config() );
virtual ~FacemarkNEW(){};
};
#include "precomp.hpp"
namespace cv
{
FacemarkNEW::Config::Config(){
detect_thresh = 0.5;
sigma=0.2;
}
*this = FacemarkNEW::Config();
if (!fn["detect_thresh"].empty())
fn["detect_thresh"] >> detect_thresh;
if (!fn["sigma"].empty())
fn["sigma"] >> sigma;
}
fs << "detect_thresh" << detect_thresh;
fs << "sigma" << sigma;
}
class FacemarkNEWImpl : public FacemarkNEW {
public:
FacemarkNEWImpl( const FacemarkNEW::Config &conf = FacemarkNEW::Config() );
void read(
const FileNode& );
void write( FileStorage& )
const;
void loadModel(
String filename);
Config config;
protected:
void training();
Config config;
};
Ptr<FacemarkNEW> FacemarkNEW::create(const FacemarkNEW::Config &conf){
return Ptr<FacemarkNEWImpl>(new FacemarkNEWImpl(conf));
}
FacemarkNEWImpl::FacemarkNEWImpl( const FacemarkNEW::Config &conf ) :
config( conf )
{
}
return true;
}
void FacemarkNEWImpl::training(){
printf("training\n");
}
bool FacemarkNEWImpl::fit(
void * runtime_params)
{
if(runtime_params!=0){
}
printf("fitting\n");
return 0;
}
config.read( fn );
}
config.write( fs );
}
void FacemarkNEWImpl::loadModel(
String filename){
}
faceDetector = f;
isSetDetector = true;
return true;
}
if(!isSetDetector){
return false;
}
if(extra_params!=0){
}
std::vector<Rect> & faces = *(std::vector<Rect>*)roi.getObj();
faces.clear();
faceDetector(image.getMat(), faces, extra_params);
return true;
}
}
Best Practice
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
struct CV_EXPORTS Params
{
Params( Mat rot = Mat::eye(2,2,
CV_32F),
float scaling = 1.0
);
Mat R;
};
Here is a snippet to extract the extra parameters:
if(runtime_params!=0){
Telo* conf = (Telo*)params;
Params* params
std::vector<Params> params = *(std::vector<Params>*)runtime_params;
for(size_t i=0; i<params.size();i++){
fit(img, landmarks[i], params[i].R,params[i].t, params[i].scale);
}
}else{
}
And here is an example to pass the extra parameter into fit function
FacemarkAAM::Params * params = new FacemarkAAM::Params(R,T,scale);
facemark->fit(image, faces, landmarks, params)
In order to understand this scheme, here is a simple example that you can try to compile and see how it works.
struct Params{
int x,y;
Params(int _x, int _y);
};
Params::Params(int _x,int _y){
x = _x;
y = _y;
}
void test(int a, void * params=0){
printf("a:%i\n", a);
if(params!=0){
Params* params = (Params*)params;
printf("extra parameters:%i %i\n", params->x, params->y);
}
}
int main(){
Params* params = new Params(7,22);
test(99, params);
return 0;
}
- Minimize the dependency It is highly recomended to keep the code as small as possible when compiled. For this purpose, the developers are ecouraged to avoid the needs of heavy dependency such as
imgcodecs
and highgui
.
- Documentation and examples Please update the documentation whenever needed and put example code for the new algorithm.
- Test codes An algorithm should be accompanied with its corresponding test code to ensure that the algorithm is compatible with various types of environment (Linux, Windows64, Windows32, Android, etc). There are several basic test that should be performed as demonstrated in the test/test_facemark_lbf.cpp file including cration of its instance, add training data, perform the training process, load a trained model, and perform the fitting to obtain facial landmarks.
- Data organization It is advised to divide the data for a new algorithm into 3 parts :
public:
struct CV_EXPORTS Params
{
}
struct CV_EXPORTS Config
{
}
struct CV_EXPORTS Model
{
}
static Ptr<FacemarkNEW> create(const FacemarkNEW::Config &conf = FacemarkNEW::Config() );
virtual ~FacemarkNEW(){};
}