Сериализация признаков лица для распознавания в DLIB

Я пишу код dlib для распознавания лиц от 1 до 1.

Я следовал примеру кода в примерах dlib и сделал следующее:

std::vector<matrix<rgb_pixel>> faces;
for (auto face : detector(img1))
{
    auto shape = sp(img1, face);
    matrix<rgb_pixel> face_chip;
    extract_image_chip(img1, get_face_chip_details(shape, 150, 0.25), face_chip);
    faces.push_back(move(face_chip));
}

это для первого изображения, а затем то же самое для второго изображения:

for (auto face : detector(img2))
{
    auto shape = sp(img2, face);
    matrix<rgb_pixel> face_chip;
    extract_image_chip(img2, get_face_chip_details(shape, 150, 0.25), face_chip);
    faces.push_back(move(face_chip));
}

затем я продолжаю по указанной ссылке:

std::vector<matrix<float, 0, 1>> face_descriptors = net(faces);
std::vector<sample_pair> edges;
for (size_t i = 0; i < face_descriptors.size(); ++i)
{
     for (size_t j = i; j < face_descriptors.size(); ++j)
     {
          if (length(face_descriptors[i] - face_descriptors[j]) < threshold)
              edges.push_back(sample_pair(i, j));
     }
 }
 std::vector<unsigned long> labels;
 const int num_clusters = chinese_whispers(edges, labels);
//etc

а теперь мой вопрос. img1 — это изображение, уже доступное коду, который считывается, когда мне нужно сопоставить конкретного человека. (т.е. если я хочу сделать mach personX, img1 читается с использованием

load_image(img1, "personX.jpg");

Вместо сохранения изображения я пытался сохранить функции и загрузить их, чтобы сократить время, затрачиваемое на извлечение функций. Итак, что я сделал, так это переместил первый цикл for в другую функцию (например, регистрацию) и сделал это примерно так:

std::vector<matrix<rgb_pixel>> faces;
for (auto face : detector(img1))
{
    auto shape = sp(img1, face);
    matrix<rgb_pixel> face_chip;
    extract_image_chip(img1, get_face_chip_details(shape, 150, 0.25), face_chip);
    serialize("personX.dat") <<face_chip;
}

то при распознавании вместо петли я использовал

matrix<rgb_pixel> face_chip;
deserialize("personX.dat")>>face_chip;            
faces.push_back(move(face_chip));

а остальной код от извлечения img2 и далее остался прежним. код скомпилирован. Но во время выполнения, когда я достигаю признания, я получаю следующую ошибку:

**************************** ОБНАРУЖЕНА ФАТАЛЬНАЯ ОШИБКА ******************* *********

Обнаружена ошибка в строке 216. Обнаружена ошибка в файле /usr/local/include/dlib/dnn/input.h. В функции обнаружена ошибка длинное целое число без знака NR = 150ul; long unsigned int NC = 150ul].

Неверным выражением было i->nr()==NR && i->nc()==NC input_rgb_image_sized::to_tensor()

Все входные изображения должны иметь 150 строк и 150 столбцов, но мы получили одно с 0 строками и 0 столбцами.

Что-то не так с сериализацией/десериализацией? или я должен записать функции в файл другим методом?

код для полной функции:

try
{
    load_image(img1, check_image);
}
catch (...)
{
    cout<<"Name: "<<uname<<" doesn't exist"<<endl;
    return;
}

else
{
    QElapsedTimer timer;
    timer.start();


    dlib::assign_image(img2, dlib::cv_image<bgr_pixel>(colorImage));
    std::vector<matrix<rgb_pixel>> faces;

    for (auto face : detector(img1))
    {
        auto shape = sp(img1, face);
        matrix<rgb_pixel> face_chip;
        extract_image_chip(img1, get_face_chip_details(shape, 150, 0.25), face_chip);
        faces.push_back(move(face_chip));
//                serialize("out.dat")<<face_chip;   //used whin i dont need to read image
    }

//            matrix<rgb_pixel> face_chip; //used whin i dont need to read image
//            deserialize("out.dat")>>face_chip; //used whin i dont need to read image
//            faces.push_back(move(face_chip)); //used whin i dont need to read image

    cout<<"Time to extract features for enroled image: "<<timer.elapsed()<<endl;
    timer.restart();

    for (auto face : detector(img2))
    {
        auto shape = sp(img2, face);
        matrix<rgb_pixel> face_chip;
        extract_image_chip(img2, get_face_chip_details(shape, 150, 0.25), face_chip);
        faces.push_back(move(face_chip));
    }

    cout<<"Time to extract features for new image: "<<timer.elapsed()<<endl;
    timer.restart();

    if (faces.size() < 2)
    {
        cout<<"No Face"<<endl;
    }

    else
    {
        std::vector<matrix<float, 0, 1>> face_descriptors = net(faces);
        std::vector<sample_pair> edges;
        for (size_t i = 0; i < face_descriptors.size(); ++i)
        {
            for (size_t j = i; j < face_descriptors.size(); ++j)
            {
                if (length(face_descriptors[i] - face_descriptors[j]) < threshold)
                    edges.push_back(sample_pair(i, j));
            }
        }
        std::vector<unsigned long> labels;
        const int num_clusters = chinese_whispers(edges, labels);

        if (num_clusters == 1)
        {
            cout<<"Recognized"<<endl;
        }
        else
        {
                    cout<<"Faces don't match";
        }
    }

    cout<<"Needed time is: "<<timer.elapsed()<<" ms"<<endl;
}

person EYakoumi    schedule 30.05.2018    source источник
comment
можете ли вы дать ссылку на суть или что-то из полного src? Кроме того, вы уверены, что ваши изображения хороши (то есть имеют лицо и правильный размер)?   -  person Joshua Smith    schedule 30.05.2018
comment
я опубликую код в качестве ответа относительно изображений да, я уверен, что у меня есть лица в них, как будто я не использую сериализацию, я правильно получаю результат сопоставления   -  person EYakoumi    schedule 30.05.2018
comment
я добавил код к вопросу. закомментированные части кода - это то, что я надеюсь использовать, чтобы избежать извлечения функции изображения каждый раз, когда для человека требуется сопоставление. Короче говоря, я хочу, чтобы функции были извлечены. сохраняется в файл, затем всякий раз, когда мне нужно сопоставить этого конкретного человека, я читаю его файл и извлекаю только функции входящего изображения и, таким образом, экономлю половину времени, необходимого для сопоставления   -  person EYakoumi    schedule 30.05.2018


Ответы (1)


вместо сериализации Матрицы я сериализовал выходной вектор (лица).

serialize("personX.dat")<<faces;

затем при распознавании я десериализовал файл dat и использовал полученный вектор:

std::vector<matrix<rgb_pixel>> faces;
deserialize("out.dat")>>faces;
for (auto face : detector(img2))
{
    auto shape = sp(img2, face);
    matrix<rgb_pixel> face_chip;
    extract_image_chip(img2, get_face_chip_details(shape, 150, 0.25), face_chip);
    faces.push_back(move(face_chip));
}

и я продолжил, как указано в вопросе.

Я не знаю, лучший ли это способ сделать это... но это сработало.

person EYakoumi    schedule 31.05.2018