我试图在Visual中使用C++应用程序构建德利卜的ex.cpp,构建应用程序由命令promt和经过训练的模型和图像文件作为参数传递。
face_landmark_detection_ex.exe shape_predictor_68_face_landmarks.dat image.jpg
该shape_predictor_68_face_landmarks.dat
是68个地标对输入图像执行检测的训练模型,每次执行任何检测都需要在运行时加载。我正试着做下面的事情。
是否有任何方法将此文件打包到我的应用程序中,以减少运行物理内存。
更新:
如何将此landmarks.dat文件存储在静态缓冲区中,以便每次预测器都可以从该缓冲区中读取。
发布于 2016-06-11 07:31:21
是的,这是可能的,但取决于Visual而不是跨平台。
1. deserialize from this stream with dlib::deserialize
下面是一个很小的例子,但是没有资源读取:
#include <string>
#include <iostream>
#include <dlib/image_processing/shape_predictor.h>
struct membuf : std::streambuf {
membuf(char const* base, size_t size) {
char* p(const_cast<char*>(base));
this->setg(p, p, p + size);
}
};
struct imemstream : virtual membuf, std::istream {
imemstream(char const* base, size_t size)
: membuf(base, size)
, std::istream(static_cast<std::streambuf*>(this)) {
}
};
using namespace dlib; //its important to use namespace dlib for deserialize work correctly
using namespace std;
int main(int argc, const char* argv[])
{
const char* file_name = "shape_predictor_68_face_landmarks.dat";
ifstream fs(file_name, ios::binary | ios::ate);
streamsize size = fs.tellg();
fs.seekg(0, ios::beg);
std::vector<char> buffer(size);
if (fs.read(buffer.data(), size))
{
cout << "Successfully read " << size << " bytes from " << file_name << " into buffer" << endl;
imemstream stream(&buffer.front(), size); // here we are loading from memory buffer. you can change this line to use pointer from Resource
shape_predictor sp;
deserialize(sp, stream);
cout << "Deserialized shape_predictor" << endl;
}
else cout << "Failed to read " << file_name << " into buffer" << endl;
return 0;
}
以及内存的使用。
首先,您应该知道shape_predictor::operator()是const,文档说,对于不同的线程使用一个shape_predictor是安全的。
因此,您可以在程序开始时创建一个shape_predictor,并多次使用它,甚至可以使用不同的线程。
接下来,在资源中放置形状预测器将使它在程序启动时被加载到RAM中,但是从资源反序列化它会复制这个内存,这将导致RAM的使用开销。如果您需要尽可能少地使用RAM -您应该从文件中加载它。
最后一个问题--如何通过编译器初始化它。它没有现成的解决方案,但是您可以使用for _prestor.h/反序列化函数中的代码并手动加载它。我认为,这是一个糟糕的解决方案,因为与加载文件相比,您不会得到更少的内存使用量。
因此,我的建议是从文件中加载一个shape_predictor,并将其全局用于所有线程。
发布于 2019-11-09 22:12:07
我知道这是一个老问题,但是Visual唯一的解决方案在我的情况下是行不通的,因为我在Linux中使用dlib
。下面是我想出的一个Unix兼容的解决方案。
我所做的是使用xxd工具将模型文件转换为文件内容的unsigned char []
表示,将其写入自定义头文件,并在deserialize
中使用它(而不是在执行过程中读取文件)。
下面的命令将生成shape_predictor_68_face_landmarks.dat
的头文件
xxd -i shape_predictor_68_face_landmarks.dat > shape_predictor_68_face_landmarks.hpp
如果您查看shape_predictor_68_face_landmarks.hpp
内部,将有两个变量:包含模型文件内容的unsigned char []
类型的shape_predictor_68_face_landmarks_dat
和unsigned int
类型的shape_predictor_68_face_landmarks_dat_len
。
在dlib
驱动程序代码中,可以执行以下操作
...
#include "shape_predictor_68_face_landmarks.hpp"
...
shape_predictor sp;
std::stringstream landmarksstream;
landmarksstream.write((const char*)shape_predictor_68_face_landmarks_dat, shape_predictor_68_face_landmarks_dat_len);
deserialize(sp, landmarksstream);
警告词:在打开由xxd
生成的文件时要小心,因为它们可能相当大,导致文本编辑器崩溃。
我不能回答这个方法的效率,但它确实允许在编译时而不是在执行时“读取”模型文件。
https://stackoverflow.com/questions/37724457
复制相似问题