Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions modules/face/include/opencv2/face/facemark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ class CV_EXPORTS_W Facemark : public virtual Algorithm
@endcode
*/
CV_WRAP virtual bool fit( InputArray image,
const std::vector<Rect>& faces,
CV_OUT std::vector<std::vector<Point2f> >& landmarks ) = 0;
InputArray faces,
OutputArrayOfArrays landmarks) = 0;
}; /* Facemark*/


Expand Down
2 changes: 1 addition & 1 deletion modules/face/include/opencv2/face/facemarkAAM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class CV_EXPORTS_W FacemarkAAM : public FacemarkTrain
};

//! overload with additional Config structures
virtual bool fitConfig( InputArray image, const std::vector<Rect>& roi, std::vector<std::vector<Point2f> >& _landmarks, const std::vector<Config> &runtime_params ) = 0;
virtual bool fitConfig( InputArray image, InputArray roi, OutputArrayOfArrays _landmarks, const std::vector<Config> &runtime_params ) = 0;


//! initializer
Expand Down
29 changes: 29 additions & 0 deletions modules/face/samples/landmarks_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import random
import numpy as np
import cv2 as cv

frame1 = cv.imread(cv.samples.findFile('lena.jpg'))
if frame1 is None:
print("image not found")
exit()
frame = np.vstack((frame1,frame1))
facemark = cv.face.createFacemarkLBF()
try:
facemark.loadModel(cv.samples.findFile('lbfmodel.yaml'))
except cv.error:
print("Model not found\nlbfmodel.yaml can be download at")
print("https://raw.githubusercontent.com/kurnianggoro/GSOC2017/master/data/lbfmodel.yaml")
cascade = cv.CascadeClassifier(cv.samples.findFile('lbpcascade_frontalface_improved.xml'))
if cascade.empty() :
print("cascade not found")
exit()
faces = cascade.detectMultiScale(frame, 1.05, 3, cv.CASCADE_SCALE_IMAGE, (30, 30))
ok, landmarks = facemark.fit(frame, faces=faces)
cv.imshow("Image", frame)
for marks in landmarks:
couleur = (random.randint(0,255),
random.randint(0,255),
random.randint(0,255))
cv.face.drawFacemarks(frame, marks, couleur)
cv.imshow("Image Landmarks", frame)
cv.waitKey()
2 changes: 1 addition & 1 deletion modules/face/src/face_alignmentimpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class FacemarkKazemiImpl : public FacemarkKazemi{
void loadModel(String fs) CV_OVERRIDE;
bool setFaceDetector(FN_FaceDetector f, void* userdata) CV_OVERRIDE;
bool getFaces(InputArray image, OutputArray faces) CV_OVERRIDE;
bool fit(InputArray image, const std::vector<Rect>& faces, CV_OUT std::vector<std::vector<Point2f> >& landmarks ) CV_OVERRIDE;
bool fit(InputArray image, InputArray faces, OutputArrayOfArrays landmarks ) CV_OVERRIDE;
void training(String imageList, String groundTruth);
bool training(vector<Mat>& images, vector< vector<Point2f> >& landmarks,string filename,Size scale,string modelFilename) CV_OVERRIDE;
// Destructor for the class.
Expand Down
49 changes: 43 additions & 6 deletions modules/face/src/facemarkAAM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ class FacemarkAAMImpl : public FacemarkAAM {

bool getData(void * items) CV_OVERRIDE;

bool fitConfig( InputArray image, const std::vector<Rect>& roi, std::vector<std::vector<Point2f> >& _landmarks, const std::vector<Config> &runtime_params ) CV_OVERRIDE;
bool fitConfig( InputArray image, InputArray roi, OutputArrayOfArrays _landmarks, const std::vector<Config> &runtime_params ) CV_OVERRIDE;

protected:

bool fit( InputArray image, const std::vector<Rect>& faces, CV_OUT std::vector<std::vector<Point2f> >& landmarks ) CV_OVERRIDE;
bool fit( InputArray image, InputArray faces, OutputArrayOfArrays landmarks ) CV_OVERRIDE;
bool fitImpl( const Mat image, std::vector<Point2f>& landmarks,const Mat R,const Point2f T,const float scale, const int sclIdx=0 );

bool addTrainingSample(InputArray image, InputArray landmarks) CV_OVERRIDE;
Expand Down Expand Up @@ -322,18 +322,54 @@ void FacemarkAAMImpl::training(void* parameters){
if(params.verbose) printf("Training is completed\n");
}

bool FacemarkAAMImpl::fit( InputArray image, const std::vector<Rect>& roi, CV_OUT std::vector<std::vector<Point2f> >& _landmarks )
/**
* @brief Copy the contents of a corners vector to an OutputArray, settings its size.
*/
static void _copyVector2Output(std::vector< std::vector< Point2f > > &vec, OutputArrayOfArrays out)
{
out.create((int)vec.size(), 1, CV_32FC2);

if (out.isMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat &m = out.getMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.isUMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
UMat &m = out.getUMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.kind() == _OutputArray::STD_VECTOR_VECTOR) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat m = out.getMat(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else {
CV_Error(cv::Error::StsNotImplemented,
"Only Mat vector, UMat vector, and vector<vector> OutputArrays are currently supported.");
}
}


bool FacemarkAAMImpl::fit( InputArray image, InputArray roi, OutputArrayOfArrays _landmarks )
{
std::vector<Config> config; // empty
return fitConfig(image, roi, _landmarks, config);
}

bool FacemarkAAMImpl::fitConfig( InputArray image, const std::vector<Rect>& roi, std::vector<std::vector<Point2f> >& _landmarks, const std::vector<Config> &configs )
bool FacemarkAAMImpl::fitConfig( InputArray image, InputArray roi, OutputArrayOfArrays _landmarks, const std::vector<Config> &configs )
{
const std::vector<Rect> & faces = roi;
Mat roimat = roi.getMat();
std::vector<Rect> faces = roimat.reshape(4, roimat.rows);
if(faces.size()<1) return false;

std::vector<std::vector<Point2f> > & landmarks = _landmarks;
std::vector<std::vector<Point2f> > landmarks;
landmarks.resize(faces.size());

Mat img = image.getMat();
Expand All @@ -354,6 +390,7 @@ bool FacemarkAAMImpl::fitConfig( InputArray image, const std::vector<Rect>& roi,
fitImpl(img, landmarks[i], R,t, scale);
}
}
_copyVector2Output(landmarks, _landmarks);

return true;
}
Expand Down
45 changes: 40 additions & 5 deletions modules/face/src/facemarkLBF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class FacemarkLBFImpl : public FacemarkLBF {

protected:

bool fit( InputArray image, const std::vector<Rect> & faces, std::vector<std::vector<Point2f> > & landmarks ) CV_OVERRIDE;//!< from many ROIs
bool fit(InputArray image, InputArray faces, OutputArrayOfArrays landmarks) CV_OVERRIDE;
bool fitImpl( const Mat image, std::vector<Point2f> & landmarks );//!< from a face

bool addTrainingSample(InputArray image, InputArray landmarks) CV_OVERRIDE;
Expand Down Expand Up @@ -370,20 +370,55 @@ void FacemarkLBFImpl::training(void* parameters){
isModelTrained = true;
}

bool FacemarkLBFImpl::fit( InputArray image, const std::vector<Rect> & roi, CV_OUT std::vector<std::vector<Point2f> > & _landmarks )
/**
* @brief Copy the contents of a corners vector to an OutputArray, settings its size.
*/
static void _copyVector2Output(std::vector< std::vector< Point2f > > &vec, OutputArrayOfArrays out)
{
const std::vector<Rect> & faces = roi;
out.create((int)vec.size(), 1, CV_32FC2);

if (out.isMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat &m = out.getMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.isUMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
UMat &m = out.getUMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.kind() == _OutputArray::STD_VECTOR_VECTOR) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat m = out.getMat(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else {
CV_Error(cv::Error::StsNotImplemented,
"Only Mat vector, UMat vector, and vector<vector> OutputArrays are currently supported.");
}
}

bool FacemarkLBFImpl::fit(InputArray image, InputArray roi, OutputArrayOfArrays _landmarks)
{
Mat roimat = roi.getMat();
std::vector<Rect> faces = roimat.reshape(4, roimat.rows);
if (faces.empty()) return false;

std::vector<std::vector<Point2f> > & landmarks = _landmarks;
std::vector<std::vector<Point2f> > landmarks;

landmarks.resize(faces.size());

for(unsigned i=0; i<faces.size();i++){
params.detectROI = faces[i];
fitImpl(image.getMat(), landmarks[i]);
}

_copyVector2Output(landmarks, _landmarks);
return true;
}

Expand Down
45 changes: 42 additions & 3 deletions modules/face/src/getlandmarks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,53 @@ void FacemarkKazemiImpl :: loadModel(String filename){
f.close();
isModelLoaded = true;
}
bool FacemarkKazemiImpl::fit(InputArray img, const std::vector<Rect>& roi, CV_OUT std::vector<std::vector<Point2f> >& landmarks){

/**
* @brief Copy the contents of a corners vector to an OutputArray, settings its size.
*/
static void _copyVector2Output(std::vector< std::vector< Point2f > > &vec, OutputArrayOfArrays out)
{
out.create((int)vec.size(), 1, CV_32FC2);

if (out.isMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat &m = out.getMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.isUMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
UMat &m = out.getUMatRef(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else if (out.kind() == _OutputArray::STD_VECTOR_VECTOR) {
for (unsigned int i = 0; i < vec.size(); i++) {
out.create(68, 1, CV_32FC2, i);
Mat m = out.getMat(i);
Mat(Mat(vec[i]).t()).copyTo(m);
}
}
else {
CV_Error(cv::Error::StsNotImplemented,
"Only Mat vector, UMat vector, and vector<vector> OutputArrays are currently supported.");
}
}


bool FacemarkKazemiImpl::fit(InputArray img, InputArray roi, OutputArrayOfArrays _landmarks)
{
if(!isModelLoaded){
String error_message = "No model loaded. Aborting....";
CV_Error(Error::StsBadArg, error_message);
return false;
}
Mat image = img.getMat();
const std::vector<Rect> & faces = roi;
std::vector<std::vector<Point2f> > & shapes = landmarks;
Mat roimat = roi.getMat();
std::vector<Rect> faces = roimat.reshape(4, roimat.rows);
std::vector<std::vector<Point2f> > shapes;
shapes.resize(faces.size());

if(image.empty()){
Expand Down Expand Up @@ -243,6 +281,7 @@ bool FacemarkKazemiImpl::fit(InputArray img, const std::vector<Rect>& roi, CV_OU
shapes[e][j].y=float(D.at<double>(1,0));
}
}
_copyVector2Output(shapes, _landmarks);
return true;
}
}//cv
Expand Down