Commit 84c882d0 authored by Alexander Alekhin's avatar Alexander Alekhin
Browse files

Merge pull request #2154 from LaurentBerger:py_face_landmark

parents fc979a85 4593e631
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -74,8 +74,8 @@ public:
    @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*/


+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ public:
    };

    //! 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
+29 −0
Original line number Diff line number Diff line
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()
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ public:
    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.
+43 −6
Original line number Diff line number Diff line
@@ -103,11 +103,11 @@ public:

    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;
@@ -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();
@@ -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;
}
Loading