【问题标题】:Serializing Face Features for recognition in DLIB序列化人脸特征以在 DLIB 中进行识别
【发布时间】:2018-11-09 09:51:03
【问题描述】:

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

我按照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));
}

然后我按照提到的链接继续:

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 是当我需要匹配特定人时读取的代码已经可用的图像。 (即,如果我想处理 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;
}

【问题讨论】:

  • 你能链接到一个要点或完整的src吗?另外,你确定你的图片很好(即有一张脸并且尺寸合适)吗?
  • 我将发布代码作为关于图像的回复是的,我确信我在其中有面孔,好像我不使用序列化我得到了正确的匹配结果
  • 我将代码添加到问题中。代码中的注释部分是我希望用来避免每次需要匹配一个人时提取图像特征的部分。所以简而言之,我希望提取特征。保存到一个文件中,然后每当我需要匹配那个特定的人时,我都会读取他的文件并仅提取传入图像的特征,从而节省了他匹配所需的一半时间

标签: c++ serialization dlib


【解决方案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));
}

我继续问题中提到的。

我不知道这是否是最好的方法……但它确实有效。

【讨论】:

    猜你喜欢
    • 2015-06-02
    • 2020-02-20
    • 2018-01-07
    • 1970-01-01
    • 2019-10-06
    • 2015-03-25
    • 2020-03-19
    • 2018-12-07
    • 2021-11-08
    相关资源
    最近更新 更多