序列化面部特征以在 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));
}
然后我继续按照问题中提到的去做。
我不知道这是否是最好的方法...但它奏效了。
我正在写一个 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,则使用
读取 img1load_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));
}
然后我继续按照问题中提到的去做。
我不知道这是否是最好的方法...但它奏效了。