Низкая точность предсказателя формы с набором данных и обучением по умолчанию

Я пытаюсь использовать dlib для обучения предсказателя формы с набором данных по умолчанию (/dlib-19.0/examples/faces/training_with_face_landmarks.xml) и образцом поезда по умолчанию (train_shape_predictor_ex.cpp).

Поэтому я хочу обучить предсказатель формы, который будет точно таким же, как предсказатель формы по умолчанию (shape_predictor_68_face_landmarks.dat), потому что я использовал тот же набор данных и тот же обучающий код. Но у меня есть некоторые проблемы.

После обучения я получаю свой файл .dat размером 16,6 МБ (но предиктор dlib по умолчанию shape_predictor_68_face_landmarks.dat имеет размер 99,7 МБ). После тестирования моего файла .dat (16,6 МБ) я получил низкую точность, но после тестирования файла .dat по умолчанию (shape_predictor_68_face_landmarks.dat, 16,6 МБ) я получил высокую точность.

Мой предсказатель формы: Мой предсказатель формы shape_predictor_68_face_landmarks.dat: shape_predictor_68_face_landmarks.dat

Подготовка:

#include <QCoreApplication>

#include <dlib/image_processing.h>
#include <dlib/data_io.h>
#include <iostream>

using namespace dlib;
using namespace std;

std::vector<std::vector<double> > get_interocular_distances (
        const std::vector<std::vector<full_object_detection> >& objects
        );

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    try
    {

        const std::string faces_directory = "/home/user/Documents/dlib-19.0/examples/faces/";

        dlib::array<array2d<unsigned char> > images_train;
        std::vector<std::vector<full_object_detection> > faces_train;

        load_image_dataset(images_train, faces_train, faces_directory+"training_with_face_landmarks.xml");

        shape_predictor_trainer trainer;

        trainer.set_oversampling_amount(300);

        trainer.set_nu(0.05);
        trainer.set_tree_depth(2);

        trainer.be_verbose();

        shape_predictor sp = trainer.train(images_train, faces_train);
        cout << "mean training error: "<<
                test_shape_predictor(sp, images_train, faces_train, get_interocular_distances(faces_train)) << endl;

        serialize(faces_directory+"sp_default_settings.dat") << sp;
    }
    catch (exception& e)
    {
        cout << "\nexception thrown!" << endl;
        cout << e.what() << endl;
    }

    return a.exec();
}

double interocular_distance (
        const full_object_detection& det
        )
{
    dlib::vector<double,2> l, r;
    double cnt = 0;
    // Find the center of the left eye by averaging the points around
    // the eye.
    for (unsigned long i = 36; i <= 41; ++i)
    {
        l += det.part(i);
        ++cnt;
    }
    l /= cnt;

    // Find the center of the right eye by averaging the points around
    // the eye.
    cnt = 0;
    for (unsigned long i = 42; i <= 47; ++i)
    {
        r += det.part(i);
        ++cnt;
    }
    r /= cnt;

    // Now return the distance between the centers of the eyes
    return length(l-r);
}

std::vector<std::vector<double> > get_interocular_distances (
        const std::vector<std::vector<full_object_detection> >& objects
        )
{
    std::vector<std::vector<double> > temp(objects.size());
    for (unsigned long i = 0; i < objects.size(); ++i)
    {
        for (unsigned long j = 0; j < objects[i].size(); ++j)
        {
            temp[i].push_back(interocular_distance(objects[i][j]));
        }
    }
    return temp;
}

Тестирование:

#include <QCoreApplication>
#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 <dlib/data_io.h>
#include <iostream>

using namespace dlib;
using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    try
        {

            // We need a face detector.  We will use this to get bounding boxes for
            // each face in an image.
            frontal_face_detector detector = get_frontal_face_detector();
            // And we also need a shape_predictor.  This is the tool that will predict face
            // landmark positions given an image and face bounding box.  Here we are just
            // loading the model from the shape_predictor_68_face_landmarks.dat file you gave
            // as a command line argument.
            shape_predictor sp;
            deserialize("/home/user/Downloads/muct-master/samples/sp_default_settings.dat") >> sp;

            string srcDir = "/home/user/Downloads/muct-master/samples/selection/";
            string dstDir = "/home/user/Downloads/muct-master/samples/my_results_default/";

            std::vector<string> vecOfImg;

            vecOfImg.push_back("i001qa-mn.jpg");
            vecOfImg.push_back("i002ra-mn.jpg");
            vecOfImg.push_back("i003ra-fn.jpg");
            vecOfImg.push_back("i003sa-fn.jpg");
            vecOfImg.push_back("i004qa-mn.jpg");
            vecOfImg.push_back("i004ra-mn.jpg");
            vecOfImg.push_back("i005ra-fn.jpg");
            vecOfImg.push_back("i006ra-mn.jpg");
            vecOfImg.push_back("i007qa-fn.jpg");
            vecOfImg.push_back("i008ra-mn.jpg");
            vecOfImg.push_back("i009qa-mn.jpg");
            vecOfImg.push_back("i009ra-mn.jpg");
            vecOfImg.push_back("i009sa-mn.jpg");
            vecOfImg.push_back("i010qa-mn.jpg");
            vecOfImg.push_back("i010sa-mn.jpg");
            vecOfImg.push_back("i011qa-mn.jpg");
            vecOfImg.push_back("i011ra-mn.jpg");
            vecOfImg.push_back("i012ra-mn.jpg");
            vecOfImg.push_back("i012sa-mn.jpg");
            vecOfImg.push_back("i014qa-fn.jpg");

            for(int imgC = 0; imgC < vecOfImg.size(); imgC++){

                array2d<rgb_pixel> img;
                load_image(img, srcDir + vecOfImg.at(imgC));
                // Make the image larger so we can detect small faces.
                pyramid_up(img);

                // Now tell the face detector to give us a list of bounding boxes
                // around all the faces in the image.
                std::vector<rectangle> dets = detector(img);
                cout << "Number of faces detected: " << dets.size() << endl;

                // Now we will go ask the shape_predictor to tell us the pose of
                // each face we detected.
                std::vector<full_object_detection> shapes;
                for (unsigned long j = 0; j < dets.size(); ++j)
                {
                    full_object_detection shape = sp(img, dets[j]);
                    cout << "number of parts: "<< shape.num_parts() << endl;
                    cout << "pixel position of first part:  " << shape.part(0) << endl;
                    cout << "pixel position of second part: " << shape.part(1) << endl;

                    for(unsigned long i = 0; i < shape.num_parts(); i++){
                        draw_solid_circle(img, shape.part(i), 2, rgb_pixel(100,255,100));
                    }

                    save_jpeg(img, dstDir + vecOfImg.at(imgC));
                    // You get the idea, you can get all the face part locations if
                    // you want them.  Here we just store them in shapes so we can
                    // put them on the screen.
                    shapes.push_back(shape);
                }

            }

        }
        catch (exception& e)
        {
            cout << "\nexception thrown!" << endl;
            cout << e.what() << endl;
        }
    return a.exec();
}

В чем разница между стандартным и моим обучением и тестированием, если я использовал набор данных и примеры по умолчанию? Как я могу обучить предсказатель формы как shape_predictor_68_face_landmarks.dat?


person konstantin_doncov    schedule 30.11.2016    source источник
comment
Несмотря на то, что вы задали вопрос на странице sourceforge (и не получили ответа), там все еще много информации. Почти уверен, что этот вопрос уже обсуждался :)   -  person Lamar Latrell    schedule 04.12.2016


Ответы (2)


Примерный набор данных (/dlib-19.0/examples/faces/training_with_face_landmarks.xml) слишком мал для обучения высококачественной модели. Это не то, на чем обучается модель, поставляемая с dlib.

В примерах используется небольшой набор данных, чтобы примеры выполнялись быстро. Смысл всех примеров в том, чтобы объяснить API dlib, а не в том, чтобы быть полезными программами. Это просто документация. Вы можете сделать что-нибудь интересное с API dlib.

person Davis King    schedule 07.04.2017
comment
Не могли бы вы рассказать мне, как я могу получить потерю ориентира-локализации для одного кадра для dlib.shape_predictor()? - person hafiz031; 06.10.2020

Он создает файл DAT размером 16,6 МБ, потому что вы либо используете несколько изображений для обучения, либо используете неправильные настройки.

Согласно этой проблеме Github, вы не используете оптимальные настройки/настройки по умолчанию во время обучения процесс.

В ваших настройках у тренера очень высокий уровень передискретизации (300), по умолчанию 20. Вы также уменьшаете мощность модели, увеличивая регуляризацию (уменьшая nu param) и используя деревья с меньшей глубиной.

Ваш нулевой параметр: 0,05. По умолчанию 0,1

Глубина вашего дерева: 2. По умолчанию 4.

Изменяя параметры и тренируясь методом проб и ошибок, вы найдете оптимальную точность при меньшем размере файла.

И имейте в виду, что каждый тренировочный процесс занимает примерно 45 минут, и вам нужен компьютер с оперативной памятью не менее 16 ГБ.

person Ezequiel Adrian    schedule 06.04.2017