序列化面部特征以在 DLIB 中进行识别

Serializing Face Features for recognition in DLIB

我正在写一个 dlib 代码来进行 1 对 1 的人脸识别。

我按照 dlib samples 中的代码示例进行了以下操作:

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));
}

然后我按照上面提到的继续link:

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 中检测到错误。 函数 void dlib::input_rgb_image_sized::to_tensor(forward_iterator, forward_iterator, dlib::resizable_tensor&) const [with forward_iterator = __gnu_cxx::__normal_iterator*, std::vector > >;长无符号整数 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;
}

我没有序列化矩阵,而是序列化了输出向量(面)。

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));
}

然后我继续按照问题中提到的去做。

我不知道这是否是最好的方法...但它奏效了。