2 votes

Comment recadrer l'image sur opencv et dlib sur Ubuntu

Je veux faire ces choses sur le dlib et opencv en utilisant c++ sur ubuntu.

  1. Détecter le visage humain en utilisant dlib. (Je l'ai déjà fait.)
  2. Couper l'image uniquement autour de la bouche.

voici mon code. Il est basé sur le code d'exemple dlib.

#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>
#include <dlib/image_processing.h>
#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <highgui.h>

using namespace dlib;
using namespace std;

// ----------------------------------------------------------------------------------------

int main(int argc, char** argv)
{  
    try
    {
        // Cet exemple prend un fichier de modèle de forme et une liste d'images à
        // traiter. Nous prendrons ces noms de fichiers en arguments de ligne de commande.
        // Dlib vient avec des images d'exemple dans le dossier examples/faces alors donnez
        // les comme arguments à ce programme.
        if (argc == 1)
        {
            cout << "Appelez ce programme comme ceci:" << endl;
            cout << "./face_landmark_detection_ex shape_predictor_68_face_landmarks.dat faces/*.jpg" << endl;
            cout << "\nVous pouvez obtenir le fichier shape_predictor_68_face_landmarks.dat depuis:\n";
            cout << "http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2" << endl;
            return 0;
        }

        // Nous avons besoin d'un détecteur de visage. Nous l'utiliserons pour obtenir des boîtes englobantes pour
        // chaque visage dans une image.
        frontal_face_detector detector = get_frontal_face_detector();
        // Et nous avons également besoin d'un shape_predictor. C'est l'outil qui prédira le visage
        // positions des repères donnés une image et une boîte englobante de visage. Ici, nous sommes juste
        // chargement du modèle depuis le fichier shape_predictor_68_face_landmarks.dat que vous avez donné
        // comme argument de ligne de commande.
        shape_predictor sp;
        deserialize(argv[1]) >> sp;
    cv::Mat cimg = cv::imread(argv[1]);

        image_window win, win_faces;
        // Boucle sur toutes les images fournies en ligne de commande.
        for (int i = 2; i < argc; ++i)
        {
            cout << "traitement de l'image " << argv[i] << endl;
            array2d<rgb_pixel> img;
            load_image(img, argv[i]);
/*
            // Agrandir l'image pour pouvoir détecter les petits visages.
            pyramid_up(img);
*/
            // Maintenant, disons au détecteur de visage de nous donner une liste de cadres de délimitation
            // autour de tous les visages dans l'image.
            std::vector<rectangle> dets = detector(img);
            cout << "Nombre de visages détectés: " << dets.size() << endl;

            // Maintenant, nous demanderons au shape_predictor de nous dire la pose de
            // chaque visage que nous avons détecté.
            std::vector<full_object_detection> shapes;
            for (unsigned long j = 0; j < dets.size(); ++j)
            {
                full_object_detection shape = sp(img, dets[j]);
                cout << "nombre de parties: "<< shape.num_parts() << endl;
                cout << "position pixel de la première partie: "  << shape.part(0) << endl;
                cout << "position pixel de la deuxième partie: " << shape.part(1) << endl;
                // Vous avez compris, vous pouvez obtenir toutes les localisations des parties du visage si
                // vous les voulez. Ici, nous les stockons juste dans shapes pour que nous puissions
                // les mettre à l'écran.
                shapes.push_back(shape);
            }

        // Recadrer l'image d'origine à la ROI définie */
        cv::Rect roi;
        roi.x = 0;
        roi.y = 0;
        roi.width = 200;
        roi.height = 200;

        cv::Mat crop = cimg(roi);
        cv::imshow("crop", crop);

            // Maintenant regardons nos poses faciales à l'écran.
/*
            win.clear_overlay();
            win.set_image(img);
            win.add_overlay(render_face_detections(shapes));

            // Nous pouvons également extraire des copies de chaque visage qui sont recadrées, tournées à la verticale,
            // et mise à l'échelle à une taille standard comme le montre ici:
            //dlib::array > face_chips;
            //extract_image_chips(img, get_face_chip_details(shapes), face_chips);
            //win_faces.set_image(tile_images(face_chips));
*/

            cout << "Appuyez sur Entrée pour traiter l'image suivante..." << endl;
            cin.get();
        }
    }
    catch (exception& e)
    {
        cout << "\nexception levée!" << endl;
        cout << e.what() << endl;
    }
}

mais ça me donne cette erreur.

Erreur OpenCV: Assertion échouée (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) dans Mat, fichier /home/bigadmin/opencv-3.1.0/modules/core/src/matrix.cpp, ligne 508

exception levée!
/home/bigadmin/opencv-3.1.0/modules/core/src/matrix.cpp:508: erreur: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows dans la fonction Mat

veuillez m'apprendre la solution pour résoudre ce problème.

merci.

1voto

Evgeniy Points 1908

Vous avez de nombreuses erreurs dans votre code :

  1. cv::Mat cimg = cv::imread(argv[1]); - argv[1] est un fichier de détection, pas une image - vous obtiendrez une image vide, c'est pourquoi votre programme plante

  2. vous ne parcourez pas les images. essayez quelque chose comme ceci :

    for (int i = 2; i < argc; ++i)
    {
        cout << "traitement de l'image " << argv[i] << endl;
        cv::Mat cvimg = cv::imgread(argv[i]);
        dlib::cv_image img(cvimg);
    ...

    Ici, vous ne lisez le fichier qu'une seule fois et vous pouvez détecter les visages

  3. vous devriez spécifier la région de rognage en fonction de la fonction de détection de visage (et encore mieux - en fonction du prédicteur de forme)

...

std::vector dets = detector(img);

ici, chaque élément dans dets est un rectangle, décrivant un visage, vous pouvez rogner comme ceci :

dlib::rectangle r = dets[j];
cv::Rect roi(r.left(), r.top(), r.width(), r.height());
cv::Mat face = cvimg(face);

Mais ce sera l'image complète du visage. Si vous voulez rogner uniquement la bouche, vous devriez utiliser la sortie du prédicteur de forme (non testé - veuillez vérifier si cela compile bien) :

full_object_detection shape = sp(img, dets[j]);
auto mouth_left = shape.part(45);
auto mouth_right = shape.part(54);
unsigned long mouth_width = (mouth_right - mouth_left).length();
double padding = 0.2;
cv::Rect roi(mouth_left.x() - mouth_width * padding, mouth_left.y() - mouth_width*0.5, mouth_width * (1 + padding * 2), mouth_width);
cv::Mat mouth = cvimg(roi);

Cela produira une image désalignée de la bouche

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X