![]() |
OpenCV 4.13.0
Open Source Computer Vision
|
このチュートリアルでは、以下の方法を学ぶ:
クラスヘッダの追加
新しいアルゴリズムのクラスヘッダは、include/opencv2/face 内の新しいファイルに追加する。新しいアルゴリズムを統合するために使用できるテンプレートを以下に示す。FacemarkNEW を新しいアルゴリズムを表す名前に変更し、それに応じた適切なファイル名で保存すること。
@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
実装コードの追加
新しいアルゴリズムを表す名前で source フォルダに新しいファイルを作成する。以下に使用できるテンプレートを示す。
@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
コードのコンパイル
build フォルダをクリアしてから、ライブラリ全体を再ビルドする。cmake に "-D BUILD_opencv_<MODULE_NAME>=OFF" フラグを追加することで、他のcontribモジュールのコンパイルを無効化できる。その後、"<build_folder>/modules/face" で make コマンドを実行すれば、コンパイル処理を高速化できる。
追加の引数の処理 追加の引数を扱うには、必要なすべての引数を保持する新しい構造体を作成する必要がある。以下は引数コンテナの例である
以下は追加の引数を取り出すスニペットである:
そして以下は追加の引数を fit 関数に渡す例である
この仕組みを理解するために、コンパイルして動作を確認できる簡単な例を以下に示す。
imgcodecs や highgui のような重い依存関係を必要とすることを避けるよう推奨される。