Как разместить 3D-модель поверх Face Landmarks, как приложение для фильтра лица? - PullRequest
1 голос
/ 26 марта 2019

Я использую две библиотеки: OpenCV для функций компьютерного зрения и OpenSceneGraph для функций компьютерной графики. Потому что основной целью программного обеспечения является дополненная реальность. Основной целью программного обеспечения является создание лицевого фильтра, такого как в Snapchat, и до сих пор я делал это с помощью лицевых ориентиров (часть компьютерного зрения) и загружал 3d-модель внутри камеры OpenCV с помощью функций OpenSceneGraph. , Проблема в том, что я пытался поместить 3d-модель на верхнюю часть наземных ориентиров, но она не работала идеально, потому что координаты модели отличаются от модели лицевых ориентиров OpenCV. Итак, есть ли способ, где я могу идеально разместить модель на вершине лицевых ориентиров?

Я пытался изменить положение модели на основе координатных точек лицевых ориентиров, но без удачи, даже если я разделил число в 10 или 20 раз, потому что координатные точки, которые берутся из лицевых ориентиров, огромный по сравнению с теми из позиции модели. Обратите внимание, что положение модели имеет три координатные точки: x, y и z, а точки, которые берутся из ориентиров лица, - это только x и y.

main.cpp

#include <iostream>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/PositionAttitudeTransform>

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include "OpenCVFuncs.hpp"

#include "/home/bardawil/Desktop/OSG-OpenCV-ARDemo/include/BackgroundCamera.h"
#include "/home/bardawil/Desktop/OSG-OpenCV-ARDemo/include/VirtualCamera.h"

using namespace cv;
using namespace cv::face;
using namespace std;

// Initialization: -

    // ** OSG Stuff **
    int screenWidth, screenHeight, textureWidth, textureHeight;
    // Create viewer
    osgViewer::Viewer viewer;
    // Main Camera
    osg::ref_ptr<osg::Camera>  camera = viewer.getCamera();
    // Background-Camera (OpenCV Feed)
    BackgroundCamera bgCamera;
    // Load glass Model as Example Scene
    osg::ref_ptr<osg::Node> glassModel = osgDB::readNodeFile("priestene test.obj");
    // Model position initial value
    osg::Vec3 modelPosition(0, 100, 10);
    // Model scale initial value
    osg::Vec3 modelScale(150, 150, 150);

    // ** OpenCV Stuff **
    // Video Capture initialization (from desktop camera)
    cv::VideoCapture cap(0);

    Mat gray;

    // Load Face Detector
    CascadeClassifier faceDetector("/home/bardawil/Desktop/OSG-OpenCV-ARDemo/haarcascade_frontalface_alt2.xml");

    // Create an instance of Facemark
    Ptr<Facemark> facemark = FacemarkLBF::create();

    struct faceParams faceStruct;
    // struct eyesLM eyes;



int main( int argc, char** argv )
{
    int count  = 0;
    facemark->loadModel("/home/bardawil/Desktop/OSG-OpenCV-ARDemo/lbfmodel.yaml");

    screenWidth = 640;
    screenHeight = 480;

    textureWidth = 640;
    textureHeight = 480;

    // OSG STUFF
    viewer.setUpViewInWindow(50,50,screenWidth,screenHeight);

    // Virtual Camera setup
    VirtualCamera* vCamera = new VirtualCamera(camera);

    // OpenCV camera
    osg::Camera* backgroundCamera = bgCamera.createCamera(textureWidth, textureHeight);

    osg::Group* glassesGroup = new osg::Group();
    // Position of glass
    osg::PositionAttitudeTransform* position = new osg::PositionAttitudeTransform();

    glassesGroup->addChild(position);
    position->addChild(glassModel);

    // Set Position of Model
    position->setPosition(modelPosition);

    // Set Scale of Model
    position->setScale(modelScale);

    // Create new group node
    osg::ref_ptr<osg::Group> group = new osg::Group;
    osg::Node* background = backgroundCamera;
    osg::Node* foreground = glassesGroup;
    background->getOrCreateStateSet()->setRenderBinDetails(1,"RenderBin");
    foreground->getOrCreateStateSet()->setRenderBinDetails(2,"RenderBin");
    group->addChild(background);
    group->addChild(foreground);
    background->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
    foreground->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);

    // Add the groud to the viewer
    viewer.setSceneData(group.get());

    if(!cap.isOpened())
    {
            std::cout << "Webcam cannot open!\n";
            return 0;
    }


    while (!viewer.done())
    {
        // Refresh Background Image
        cv::Mat frame;
        faceStruct.frame = frame;
        cap.read(frame);
        // bgCamera.update(frame);

        // Update Virtual Camera (these Coordinates should be determined by some AR-Framework/Functionality)
        // They are just updated for demonstration purposes..
        // Position Parameters: Roll, Pitch, Heading, X, Y, Z
        // vCamera->updatePosition(0, 0, 0, 0, 0, 0);
        //osg::notify(osg::WARN)<<"Angle: "<<  angleRoll <<std::endl;
        vector<Rect> faces;

        // // Convert frame to grayscale because
        // // faceDetector requires grayscale image.

        cvtColor(frame, gray, COLOR_BGR2GRAY);

        // // Detect faces
        // const int scale = 3;
        // cv::Mat frame_gray( cvRound( gray.rows / scale ), cvRound( gray.cols / scale ), CV_8UC1 );
        // cv::resize( gray, frame_gray, frame_gray.size() );
        faceDetector.detectMultiScale(gray, faces, 1.05 , 6, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

        vector< vector<Point2f> > landmarks;

        // // Run landmark detector
        bool success = facemark->fit(frame, faces, landmarks);

        if(success){
            // eyes = drawLandmarks(frame, landmarks[0]);   
            vCamera->updatePosition(0, 0, 0, 0, 0, 0);
        }
        // Display results 
        // flip(frame, frame, +1);

        // vCamera->updatePosition(0, 0, 0, 0, 0, 0);
        bgCamera.update(frame);
        viewer.frame();
    }
    return 0;
}
...