Commit 4a066317 authored by Alexander Alekhin's avatar Alexander Alekhin

Merge pull request #1428 from alalek:pr1257_refactoring

parents 1f8ccc16 e310fc55
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
...@@ -44,9 +19,9 @@ namespace face { ...@@ -44,9 +19,9 @@ namespace face {
//! @addtogroup face //! @addtogroup face
//! @{ //! @{
class CV_EXPORTS_W FacemarkAAM : public Facemark class CV_EXPORTS_W FacemarkAAM : public Facemark
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
{ {
/** /**
...@@ -80,8 +55,8 @@ namespace face { ...@@ -80,8 +55,8 @@ namespace face {
struct CV_EXPORTS Config struct CV_EXPORTS Config
{ {
Config( Mat rot = Mat::eye(2,2,CV_32F), Config( Mat rot = Mat::eye(2,2,CV_32F),
Point2f trans = Point2f(0.0,0.0), Point2f trans = Point2f(0.0f,0.0f),
float scaling = 1.0, float scaling = 1.0f,
int scale_id=0 int scale_id=0
); );
...@@ -151,7 +126,7 @@ namespace face { ...@@ -151,7 +126,7 @@ namespace face {
static Ptr<FacemarkAAM> create(const FacemarkAAM::Params &parameters = FacemarkAAM::Params() ); static Ptr<FacemarkAAM> create(const FacemarkAAM::Params &parameters = FacemarkAAM::Params() );
virtual ~FacemarkAAM() {} virtual ~FacemarkAAM() {}
}; /* AAM */ }; /* AAM */
//! @} //! @}
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
...@@ -45,9 +20,9 @@ namespace face { ...@@ -45,9 +20,9 @@ namespace face {
//! @addtogroup face //! @addtogroup face
//! @{ //! @{
class CV_EXPORTS_W FacemarkLBF : public Facemark class CV_EXPORTS_W FacemarkLBF : public Facemark
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
{ {
/** /**
...@@ -110,7 +85,7 @@ namespace face { ...@@ -110,7 +85,7 @@ namespace face {
static Ptr<FacemarkLBF> create(const FacemarkLBF::Params &parameters = FacemarkLBF::Params() ); static Ptr<FacemarkLBF> create(const FacemarkLBF::Params &parameters = FacemarkLBF::Params() );
virtual ~FacemarkLBF(){}; virtual ~FacemarkLBF(){};
}; /* LBF */ }; /* LBF */
//! @} //! @}
......
/* /*
By downloading, copying, installing or using the software you agree to this
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
...@@ -63,31 +34,31 @@ Mentor: Delia Passalacqua ...@@ -63,31 +34,31 @@ Mentor: Delia Passalacqua
* example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/lfpw.zip * example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/lfpw.zip
*--------------------------------------------------*/ *--------------------------------------------------*/
#include <stdio.h> #include <stdio.h>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "opencv2/face.hpp" #include "opencv2/face.hpp"
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <ctime> #include <ctime>
using namespace std; using namespace std;
using namespace cv; using namespace cv;
using namespace cv::face; using namespace cv::face;
bool myDetector( InputArray image, OutputArray ROIs, CascadeClassifier face_cascade); bool myDetector( InputArray image, OutputArray ROIs, CascadeClassifier *face_cascade);
bool getInitialFitting(Mat image, Rect face, std::vector<Point2f> s0, bool getInitialFitting(Mat image, Rect face, std::vector<Point2f> s0,
CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale); CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale);
bool parseArguments(int argc, char** argv, CommandLineParser & , String & cascade, bool parseArguments(int argc, char** argv, CommandLineParser & , String & cascade,
String & model, String & images, String & annotations, String & testImages String & model, String & images, String & annotations, String & testImages
); );
int main(int argc, char** argv ) int main(int argc, char** argv )
{ {
CommandLineParser parser(argc, argv,""); CommandLineParser parser(argc, argv,"");
String cascade_path,eyes_cascade_path,images_path, annotations_path, test_images_path; String cascade_path,eyes_cascade_path,images_path, annotations_path, test_images_path;
if(!parseArguments(argc, argv, parser,cascade_path,eyes_cascade_path,images_path, annotations_path, test_images_path)) if(!parseArguments(argc, argv, parser,cascade_path,eyes_cascade_path,images_path, annotations_path, test_images_path))
...@@ -159,7 +130,7 @@ Mentor: Delia Passalacqua ...@@ -159,7 +130,7 @@ Mentor: Delia Passalacqua
printf("image #%i ", i); printf("image #%i ", i);
//! [detect_face] //! [detect_face]
image = imread(images[i]); image = imread(images[i]);
myDetector(image, faces, face_cascade); myDetector(image, faces, &face_cascade);
//! [detect_face] //! [detect_face]
if(faces.size()>0){ if(faces.size()>0){
//! [get_initialization] //! [get_initialization]
...@@ -194,25 +165,26 @@ Mentor: Delia Passalacqua ...@@ -194,25 +165,26 @@ Mentor: Delia Passalacqua
} //for } //for
//! [fitting] //! [fitting]
} }
bool myDetector( InputArray image, OutputArray ROIs, CascadeClassifier face_cascade){ bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
{
Mat gray; Mat gray;
std::vector<Rect> & faces = *(std::vector<Rect>*) ROIs.getObj();
faces.clear();
if(image.channels()>1){ if (image.channels() > 1)
cvtColor(image.getMat(),gray,CV_BGR2GRAY); cvtColor(image, gray, COLOR_BGR2GRAY);
}else{ else
gray = image.getMat().clone(); gray = image.getMat().clone();
}
equalizeHist( gray, gray );
face_cascade.detectMultiScale( gray, faces, 1.2, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) ); equalizeHist(gray, gray);
std::vector<Rect> faces_;
face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
Mat(faces_).copyTo(faces);
return true; return true;
} }
bool getInitialFitting(Mat image, Rect face, std::vector<Point2f> s0 ,CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale){ bool getInitialFitting(Mat image, Rect face, std::vector<Point2f> s0 ,CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale){
std::vector<Point2f> mybase; std::vector<Point2f> mybase;
std::vector<Point2f> T; std::vector<Point2f> T;
std::vector<Point2f> base = Mat(Mat(s0)+Scalar(image.cols/2,image.rows/2)).reshape(2); std::vector<Point2f> base = Mat(Mat(s0)+Scalar(image.cols/2,image.rows/2)).reshape(2);
...@@ -230,7 +202,7 @@ Mentor: Delia Passalacqua ...@@ -230,7 +202,7 @@ Mentor: Delia Passalacqua
std::vector<Rect> eyes; std::vector<Rect> eyes;
//-- In each face, detect eyes //-- In each face, detect eyes
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(20, 20) ); eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, CASCADE_SCALE_IMAGE, Size(20, 20) );
if(eyes.size()==2){ if(eyes.size()==2){
found = true; found = true;
int j=0; int j=0;
...@@ -273,15 +245,15 @@ Mentor: Delia Passalacqua ...@@ -273,15 +245,15 @@ Mentor: Delia Passalacqua
Trans = Point2f( (float)(face.x + face.width*0.5),(float)(face.y + face.height*0.5)); Trans = Point2f( (float)(face.x + face.width*0.5),(float)(face.y + face.height*0.5));
} }
return found; return found;
} }
bool parseArguments(int argc, char** argv, CommandLineParser & parser, bool parseArguments(int argc, char** argv, CommandLineParser & parser,
String & cascade, String & cascade,
String & model, String & model,
String & images, String & images,
String & annotations, String & annotations,
String & test_images String & test_images
){ ){
const String keys = const String keys =
"{ @f face-cascade | | (required) path to the cascade model file for the face detector }" "{ @f face-cascade | | (required) path to the cascade model file for the face detector }"
"{ @e eyes-cascade | | (required) path to the cascade model file for the eyes detector }" "{ @e eyes-cascade | | (required) path to the cascade model file for the eyes detector }"
...@@ -315,4 +287,4 @@ Mentor: Delia Passalacqua ...@@ -315,4 +287,4 @@ Mentor: Delia Passalacqua
return false; return false;
} }
return true; return true;
} }
/* /*
By downloading, copying, installing or using the software you agree to this
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
...@@ -63,27 +34,26 @@ Mentor: Delia Passalacqua ...@@ -63,27 +34,26 @@ Mentor: Delia Passalacqua
* example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/ibug.zip * example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/ibug.zip
*--------------------------------------------------*/ *--------------------------------------------------*/
#include <stdio.h> #include <stdio.h>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "opencv2/face.hpp" #include "opencv2/face.hpp"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
using namespace cv::face; using namespace cv::face;
CascadeClassifier face_cascade; static bool myDetector( InputArray image, OutputArray roi, CascadeClassifier *face_detector);
bool myDetector( InputArray image, OutputArray roi, void * config=0 ); static bool parseArguments(int argc, char** argv, CommandLineParser & , String & cascade,
bool parseArguments(int argc, char** argv, CommandLineParser & , String & cascade,
String & model, String & images, String & annotations, String & testImages String & model, String & images, String & annotations, String & testImages
); );
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
CommandLineParser parser(argc, argv,""); CommandLineParser parser(argc, argv,"");
String cascade_path,model_path,images_path, annotations_path, test_images_path; String cascade_path,model_path,images_path, annotations_path, test_images_path;
if(!parseArguments(argc, argv, parser,cascade_path,model_path,images_path, annotations_path, test_images_path)) if(!parseArguments(argc, argv, parser,cascade_path,model_path,images_path, annotations_path, test_images_path))
...@@ -95,8 +65,9 @@ Mentor: Delia Passalacqua ...@@ -95,8 +65,9 @@ Mentor: Delia Passalacqua
params.cascade_face = cascade_path; params.cascade_face = cascade_path;
Ptr<Facemark> facemark = FacemarkLBF::create(params); Ptr<Facemark> facemark = FacemarkLBF::create(params);
CascadeClassifier face_cascade;
face_cascade.load(params.cascade_face.c_str()); face_cascade.load(params.cascade_face.c_str());
facemark->setFaceDetector(myDetector); facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
/*Loads the dataset*/ /*Loads the dataset*/
std::vector<String> images_train; std::vector<String> images_train;
...@@ -147,37 +118,32 @@ Mentor: Delia Passalacqua ...@@ -147,37 +118,32 @@ Mentor: Delia Passalacqua
cout<<"face not found"<<endl; cout<<"face not found"<<endl;
} }
} }
}
} bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
{
bool myDetector( InputArray image, OutputArray roi, void * config ){
Mat gray; Mat gray;
std::vector<Rect> & faces = *(std::vector<Rect>*) roi.getObj();
faces.clear();
if(config!=0){ if (image.channels() > 1)
//do nothing cvtColor(image, gray, COLOR_BGR2GRAY);
} else
if(image.channels()>1){
cvtColor(image,gray,CV_BGR2GRAY);
}else{
gray = image.getMat().clone(); gray = image.getMat().clone();
}
equalizeHist( gray, gray );
face_cascade.detectMultiScale( gray, faces, 1.4, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) ); equalizeHist(gray, gray);
std::vector<Rect> faces_;
face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
Mat(faces_).copyTo(faces);
return true; return true;
} }
bool parseArguments(int argc, char** argv, CommandLineParser & parser, bool parseArguments(int argc, char** argv, CommandLineParser & parser,
String & cascade, String & cascade,
String & model, String & model,
String & images, String & images,
String & annotations, String & annotations,
String & test_images String & test_images
){ ){
const String keys = const String keys =
"{ @c cascade | | (required) path to the face cascade xml file fo the face detector }" "{ @c cascade | | (required) path to the face cascade xml file fo the face detector }"
"{ @i images | | (required) path of a text file contains the list of paths to all training images}" "{ @i images | | (required) path of a text file contains the list of paths to all training images}"
...@@ -214,4 +180,4 @@ Mentor: Delia Passalacqua ...@@ -214,4 +180,4 @@ Mentor: Delia Passalacqua
} }
return true; return true;
} }
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
...@@ -47,7 +18,7 @@ Mentor: Delia Passalacqua ...@@ -47,7 +18,7 @@ Mentor: Delia Passalacqua
#include <stdio.h> #include <stdio.h>
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
...@@ -57,9 +28,8 @@ using namespace std; ...@@ -57,9 +28,8 @@ using namespace std;
using namespace cv; using namespace cv;
using namespace cv::face; using namespace cv::face;
CascadeClassifier face_cascade; static bool myDetector(InputArray image, OutputArray ROIs, CascadeClassifier *face_cascade);
bool myDetector( InputArray image, OutputArray ROIs, void * config = 0); static bool parseArguments(int argc, char** argv, CommandLineParser & parser,
bool parseArguments(int argc, char** argv, CommandLineParser & parser,
String & cascade, String & model,String & video); String & cascade, String & model,String & video);
int main(int argc, char** argv ){ int main(int argc, char** argv ){
...@@ -68,6 +38,7 @@ int main(int argc, char** argv ){ ...@@ -68,6 +38,7 @@ int main(int argc, char** argv ){
if(!parseArguments(argc, argv, parser,cascade_path,model_path,video_path)) if(!parseArguments(argc, argv, parser,cascade_path,model_path,video_path))
return -1; return -1;
CascadeClassifier face_cascade;
face_cascade.load(cascade_path); face_cascade.load(cascade_path);
FacemarkLBF::Params params; FacemarkLBF::Params params;
...@@ -75,7 +46,7 @@ int main(int argc, char** argv ){ ...@@ -75,7 +46,7 @@ int main(int argc, char** argv ){
params.cascade_face = cascade_path; params.cascade_face = cascade_path;
Ptr<Facemark> facemark = FacemarkLBF::create(params); Ptr<Facemark> facemark = FacemarkLBF::create(params);
facemark->setFaceDetector(myDetector); facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
facemark->loadModel(params.model_filename.c_str()); facemark->loadModel(params.model_filename.c_str());
VideoCapture capture(video_path); VideoCapture capture(video_path);
...@@ -144,23 +115,20 @@ int main(int argc, char** argv ){ ...@@ -144,23 +115,20 @@ int main(int argc, char** argv ){
waitKey(0); // key press to close window waitKey(0); // key press to close window
} }
bool myDetector( InputArray image, OutputArray ROIs, void * config ){ bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
{
Mat gray; Mat gray;
std::vector<Rect> & faces = *(std::vector<Rect>*) ROIs.getObj();
faces.clear();
if(config!=0){
//do nothing
}
if(image.channels()>1){ if (image.channels() > 1)
cvtColor(image.getMat(),gray,CV_BGR2GRAY); cvtColor(image, gray, COLOR_BGR2GRAY);
}else{ else
gray = image.getMat().clone(); gray = image.getMat().clone();
}
equalizeHist( gray, gray );
face_cascade.detectMultiScale( gray, faces, 1.4, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) ); equalizeHist(gray, gray);
std::vector<Rect> faces_;
face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
Mat(faces_).copyTo(faces);
return true; return true;
} }
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
*/ */
#include "precomp.hpp"
#include "opencv2/face.hpp" #include "opencv2/face.hpp"
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "precomp.hpp"
/*dataset parser*/ /*dataset parser*/
#include <fstream> #include <fstream>
...@@ -46,36 +22,38 @@ Mentor: Delia Passalacqua ...@@ -46,36 +22,38 @@ Mentor: Delia Passalacqua
namespace cv { namespace cv {
namespace face { namespace face {
CParams::CParams(String s, double sf, int minN, Size minSz, Size maxSz){
using namespace std;
CParams::CParams(String s, double sf, int minN, Size minSz, Size maxSz){
cascade = s; cascade = s;
scaleFactor = sf; scaleFactor = sf;
minNeighbors = minN; minNeighbors = minN;
minSize = minSz; minSize = minSz;
maxSize = maxSz; maxSize = maxSz;
if (!face_cascade.load(cascade))
{
CV_Error_(Error::StsBadArg, ("Error loading face_cascade: %s", cascade.c_str()));
} }
}
bool getFaces(InputArray image, OutputArray faces, void * parameters){ bool getFaces(InputArray image, OutputArray faces, CParams* params)
{
CV_Assert(params);
Mat gray; Mat gray;
std::vector<Rect> roi; std::vector<Rect> roi;
if(parameters!=0){ cvtColor(image.getMat(), gray, COLOR_BGR2GRAY);
CParams * params = (CParams *)parameters; equalizeHist(gray, gray);
cvtColor( image.getMat(), gray, CV_BGR2GRAY );
equalizeHist( gray, gray );
CascadeClassifier face_cascade; params->face_cascade.detectMultiScale( gray, roi, params->scaleFactor, params->minNeighbors, CASCADE_SCALE_IMAGE, params->minSize, params->maxSize);
if( !face_cascade.load( params->cascade ) ){ printf("--(!)Error loading face_cascade\n"); return false; };
face_cascade.detectMultiScale( gray, roi, params->scaleFactor, params->minNeighbors, 0|CV_HAAR_SCALE_IMAGE, params->minSize, params->maxSize);
Mat(roi).copyTo(faces); Mat(roi).copyTo(faces);
return true; return true;
}else{ }
return false;
}
}
bool loadDatasetList(String imageList, String groundTruth, std::vector<String> & images, std::vector<String> & landmarks){ bool loadDatasetList(String imageList, String groundTruth, std::vector<String> & images, std::vector<String> & landmarks){
std::string line; std::string line;
/*clear the output containers*/ /*clear the output containers*/
...@@ -103,22 +81,22 @@ namespace face { ...@@ -103,22 +81,22 @@ namespace face {
} }
return true; return true;
} }
bool loadTrainingData(String filename, std::vector<String> & images, OutputArray _facePoints, char delim, float offset){ bool loadTrainingData(String filename, std::vector<String> & images, OutputArray _facePoints, char delim, float offset){
std::string line; std::string line;
std::string item; std::string item;
std::vector<Point2f> pts; std::vector<Point2f> pts;
std::vector<float> raw; std::vector<float> raw;
// FIXIT
std::vector<std::vector<Point2f> > & facePoints = std::vector<std::vector<Point2f> > & facePoints =
*(std::vector<std::vector<Point2f> >*) _facePoints.getObj(); *(std::vector<std::vector<Point2f> >*) _facePoints.getObj();
std::ifstream infile; std::ifstream infile;
infile.open(filename.c_str(), std::ios::in); infile.open(filename.c_str(), std::ios::in);
if (!infile) { if (!infile) {
std::string error_message = "No valid input file was given, please check the given filename."; CV_Error_(Error::StsBadArg, ("No valid input file was given, please check the given filename: %s", filename.c_str()));
CV_Error(CV_StsBadArg, error_message);
} }
/*clear the output containers*/ /*clear the output containers*/
...@@ -148,12 +126,13 @@ namespace face { ...@@ -148,12 +126,13 @@ namespace face {
} // main loading process } // main loading process
return true; return true;
} }
bool loadTrainingData(String imageList, String groundTruth, std::vector<String> & images, OutputArray _facePoints, float offset){ bool loadTrainingData(String imageList, String groundTruth, std::vector<String> & images, OutputArray _facePoints, float offset){
std::string line; std::string line;
std::vector<Point2f> facePts; std::vector<Point2f> facePts;
// FIXIT
std::vector<std::vector<Point2f> > & facePoints = std::vector<std::vector<Point2f> > & facePoints =
*(std::vector<std::vector<Point2f> >*) _facePoints.getObj(); *(std::vector<std::vector<Point2f> >*) _facePoints.getObj();
...@@ -165,8 +144,7 @@ namespace face { ...@@ -165,8 +144,7 @@ namespace face {
std::ifstream infile; std::ifstream infile;
infile.open(imageList.c_str(), std::ios::in); infile.open(imageList.c_str(), std::ios::in);
if (!infile) { if (!infile) {
std::string error_message = "No valid input file was given, please check the given filename."; CV_Error_(Error::StsBadArg, ("No valid input file was given, please check the given filename: %s", imageList.c_str()));
CV_Error(CV_StsBadArg, error_message);
} }
while (getline (infile, line)){ while (getline (infile, line)){
...@@ -182,10 +160,10 @@ namespace face { ...@@ -182,10 +160,10 @@ namespace face {
} }
return true; return true;
} }
bool loadFacePoints(String filename, OutputArray points, float offset){ bool loadFacePoints(String filename, OutputArray points, float offset){
std::vector<Point2f> & pts = *(std::vector<Point2f> *)points.getObj(); vector<Point2f> pts;
std::string line, item; std::string line, item;
std::ifstream infile(filename.c_str()); std::ifstream infile(filename.c_str());
...@@ -222,16 +200,16 @@ namespace face { ...@@ -222,16 +200,16 @@ namespace face {
} }
Mat(pts).copyTo(points);
return true; return true;
} }
void drawFacemarks(InputOutputArray image, InputArray points, Scalar color){ void drawFacemarks(InputOutputArray image, InputArray points, Scalar color){
Mat img = image.getMat(); Mat img = image.getMat();
std::vector<Point2f> pts = *(std::vector<Point2f>*)points.getObj(); vector<Point2f> pts = points.getMat();
for(size_t i=0;i<pts.size();i++){ for(size_t i=0;i<pts.size();i++){
circle(img, pts[i],3, color,-1); circle(img, pts[i],3, color,-1);
} }
} //drawPoints }
} /* namespace face */ } /* namespace face */
} /* namespace cv */ } /* namespace cv */
This diff is collapsed.
This diff is collapsed.
...@@ -52,5 +52,7 @@ ...@@ -52,5 +52,7 @@
#include <set> #include <set>
#include <limits> #include <limits>
#include <iostream>
#endif #endif
/* // This file is part of OpenCV project.
By downloading, copying, installing or using the software you agree to this // It is subject to the license terms in the LICENSE file found in the top-level directory
license. If you do not agree to this license, do not download, install, // of this distribution and at http://opencv.org/license.html.
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV /*
This file contains results of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
...@@ -50,24 +25,19 @@ using namespace std; ...@@ -50,24 +25,19 @@ using namespace std;
using namespace cv; using namespace cv;
using namespace cv::face; using namespace cv::face;
CascadeClassifier face_detector; static bool customDetector( InputArray image, OutputArray ROIs, CascadeClassifier *face_detector){
static bool customDetector( InputArray image, OutputArray ROIs, void * config = 0 ){
Mat gray; Mat gray;
std::vector<Rect> & faces = *(std::vector<Rect>*) ROIs.getObj(); std::vector<Rect> & faces = *(std::vector<Rect>*) ROIs.getObj();
faces.clear(); faces.clear();
if(config!=0){
//do nothing
}
if(image.channels()>1){ if(image.channels()>1){
cvtColor(image.getMat(),gray,CV_BGR2GRAY); cvtColor(image.getMat(),gray, COLOR_BGR2GRAY);
}else{ }else{
gray = image.getMat().clone(); gray = image.getMat().clone();
} }
equalizeHist( gray, gray ); equalizeHist( gray, gray );
face_detector.detectMultiScale( gray, faces, 1.4, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) ); face_detector->detectMultiScale( gray, faces, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );
return true; return true;
} }
...@@ -82,11 +52,11 @@ TEST(CV_Face_FacemarkAAM, can_create_default) { ...@@ -82,11 +52,11 @@ TEST(CV_Face_FacemarkAAM, can_create_default) {
TEST(CV_Face_FacemarkAAM, can_set_custom_detector) { TEST(CV_Face_FacemarkAAM, can_set_custom_detector) {
string cascade_filename = string cascade_filename =
cvtest::findDataFile("cascadeandhog/cascades/lbpcascade_frontalface.xml", true); cvtest::findDataFile("cascadeandhog/cascades/lbpcascade_frontalface.xml", true);
CascadeClassifier face_detector;
EXPECT_TRUE(face_detector.load(cascade_filename)); EXPECT_TRUE(face_detector.load(cascade_filename));
Ptr<Facemark> facemark = FacemarkAAM::create(); Ptr<Facemark> facemark = FacemarkAAM::create();
EXPECT_TRUE(facemark->setFaceDetector(customDetector)); EXPECT_TRUE(facemark->setFaceDetector((cv::face::FN_FaceDetector)customDetector, &face_detector));
} }
TEST(CV_Face_FacemarkAAM, test_workflow) { TEST(CV_Face_FacemarkAAM, test_workflow) {
...@@ -106,6 +76,9 @@ TEST(CV_Face_FacemarkAAM, test_workflow) { ...@@ -106,6 +76,9 @@ TEST(CV_Face_FacemarkAAM, test_workflow) {
string cascade_filename = string cascade_filename =
cvtest::findDataFile("cascadeandhog/cascades/lbpcascade_frontalface.xml", true); cvtest::findDataFile("cascadeandhog/cascades/lbpcascade_frontalface.xml", true);
CascadeClassifier face_detector;
EXPECT_TRUE(face_detector.load(cascade_filename));
FacemarkAAM::Params params; FacemarkAAM::Params params;
params.n = 1; params.n = 1;
params.m = 1; params.m = 1;
...@@ -115,7 +88,8 @@ TEST(CV_Face_FacemarkAAM, test_workflow) { ...@@ -115,7 +88,8 @@ TEST(CV_Face_FacemarkAAM, test_workflow) {
Mat image; Mat image;
std::vector<Point2f> landmarks; std::vector<Point2f> landmarks;
for(size_t i=0;i<images_train.size();i++){ for(size_t i=0;i<images_train.size();i++)
{
image = imread(images_train[i].c_str()); image = imread(images_train[i].c_str());
EXPECT_TRUE(loadFacePoints(points_train[i].c_str(),landmarks)); EXPECT_TRUE(loadFacePoints(points_train[i].c_str(),landmarks));
EXPECT_TRUE(landmarks.size()>0); EXPECT_TRUE(landmarks.size()>0);
...@@ -125,7 +99,7 @@ TEST(CV_Face_FacemarkAAM, test_workflow) { ...@@ -125,7 +99,7 @@ TEST(CV_Face_FacemarkAAM, test_workflow) {
EXPECT_NO_THROW(facemark->training()); EXPECT_NO_THROW(facemark->training());
/*------------ Fitting Part ---------------*/ /*------------ Fitting Part ---------------*/
facemark->setFaceDetector(customDetector); EXPECT_TRUE(facemark->setFaceDetector((cv::face::FN_FaceDetector)customDetector, &face_detector));
string image_filename = cvtest::findDataFile("face/david1.jpg", true); string image_filename = cvtest::findDataFile("face/david1.jpg", true);
image = imread(image_filename.c_str()); image = imread(image_filename.c_str());
EXPECT_TRUE(!image.empty()); EXPECT_TRUE(!image.empty());
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
/* /*
By downloading, copying, installing or using the software you agree to this This file contains results of GSoC Project: Facemark API for OpenCV
license. If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall copyright holders or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
This file was part of GSoC Project: Facemark API for OpenCV
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua Mentor: Delia Passalacqua
...@@ -61,13 +36,13 @@ static bool myCustomDetector( InputArray image, OutputArray ROIs, void * config ...@@ -61,13 +36,13 @@ static bool myCustomDetector( InputArray image, OutputArray ROIs, void * config
} }
if(image.channels()>1){ if(image.channels()>1){
cvtColor(image.getMat(),gray,CV_BGR2GRAY); cvtColor(image.getMat(),gray,COLOR_BGR2GRAY);
}else{ }else{
gray = image.getMat().clone(); gray = image.getMat().clone();
} }
equalizeHist( gray, gray ); equalizeHist( gray, gray );
cascade_detector.detectMultiScale( gray, faces, 1.4, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) ); cascade_detector.detectMultiScale( gray, faces, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );
return true; return true;
} }
...@@ -141,8 +116,3 @@ TEST(CV_Face_FacemarkLBF, test_workflow) { ...@@ -141,8 +116,3 @@ TEST(CV_Face_FacemarkLBF, test_workflow) {
EXPECT_TRUE(facemark->fit(image, rects, facial_points)); EXPECT_TRUE(facemark->fit(image, rects, facial_points));
EXPECT_TRUE(facial_points[0].size()>0); EXPECT_TRUE(facial_points[0].size()>0);
} }
TEST(CV_Face_FacemarkLBF, get_data) {
Ptr<Facemark> facemark = FacemarkLBF::create();
EXPECT_TRUE(facemark->getData());
}
...@@ -69,31 +69,25 @@ struct Conf { ...@@ -69,31 +69,25 @@ struct Conf {
Conf(cv::String s, double d){ Conf(cv::String s, double d){
model_path = s; model_path = s;
scaleFactor = d; scaleFactor = d;
face_detector.load(model_path);
}; };
CascadeClassifier face_detector;
}; };
bool myDetector( InputArray image, OutputArray roi, void * config ){ bool myDetector(InputArray image, OutputArray faces, Conf *conf){
Mat gray; Mat gray;
std::vector<Rect> & faces = *(std::vector<Rect>*) roi.getObj();
faces.clear();
if(config!=0){
Conf* conf = (Conf*)config;
if(image.channels()>1){ if (image.channels() > 1)
cvtColor(image,gray,CV_BGR2GRAY); cvtColor(image, gray, COLOR_BGR2GRAY);
}else{ else
gray = image.getMat().clone(); gray = image.getMat().clone();
}
equalizeHist( gray, gray );
CascadeClassifier face_cascade(conf->model_path); equalizeHist(gray, gray);
face_cascade.detectMultiScale( gray, faces, conf->scaleFactor, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) );
std::vector<Rect> faces_;
conf->face_cascade.detectMultiScale(gray, faces_, conf->scaleFactor, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );
Mat(faces_).copyTo(faces);
return true; return true;
}else{
return false;
}
} }
@endcode @endcode
...@@ -101,8 +95,8 @@ bool myDetector( InputArray image, OutputArray roi, void * config ){ ...@@ -101,8 +95,8 @@ bool myDetector( InputArray image, OutputArray roi, void * config ){
The following snippet demonstrates how to set the custom detector to the facemark object and use it to detect the faces. Keep in mind that some facemark object might use the face detector during the training process. The following snippet demonstrates how to set the custom detector to the facemark object and use it to detect the faces. Keep in mind that some facemark object might use the face detector during the training process.
@code @code
Conf* config = new Conf("../data/lbpcascade_frontalface.xml",1.4); Conf config("../data/lbpcascade_frontalface.xml", 1.4);
facemark->setFaceDetector(myDetector); facemark->setFaceDetector(myDetector, &config); // we must guarantee proper lifetime of "config" object
@endcode @endcode
Here is the snippet for detecting face using the user defined face detector function. Here is the snippet for detecting face using the user defined face detector function.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment