是否可以在编译时加载/读取shape_predictor_68_face_landmarks.dat?
我想建立使用DLIB的face_landmark_detection_ex.cpp在Visual Studio中一个C++应用。构建应用程序从命令promt运行并且训练有素的模型和图像文件作为参数传递。是否可以在编译时加载/读取shape_predictor_68_face_landmarks.dat?
face_landmark_detection_ex.exe shape_predictor_68_face_landmarks.dat image.jpg
这shape_predictor_68_face_landmarks.dat
为68个地标上输入的图像进行检测的训练的模型,需要在运行时每执行任何检测时间来加载。我正在尝试做下列事情。
- 加载此shape_predictor_68_face_landmarks.dat在构建应用程序或编译的时间。
- 在代码中读取此shape_predictor_68_face_landmarks.dat以便每次我的应用程序执行它的执行时,它都不会占用更多的内存。
有没有什么办法可以在我的应用程序中打包这个文件,以便它将占用更少的物理内存来运行。
更新:
我怎么能存储此shape_predictor_68_face_landmarks.dat文件中的静态缓冲区,这样每次shape_predictor可以从这个缓冲区中读取。
是,其可能的,但依赖于Visual Studio和不是跨平台
你应该创建资源文件,包括hape_predictor_68_face_landmarks.dat到您的项目。详情请参阅https://msdn.microsoft.com/ru-ru/library/7zxb70x7.aspx。这将使编译器从指针把这个文件到你的EXE/DLL
打开resoure在运行时获取内存指针https://msdn.microsoft.com/en-us/library/windows/desktop/ee719660(v=vs.85).aspx
-
创建内存流(的std :: istream的)。
-
从该料流与DLIB
- 反序列化::反序列化
这里是最小的例子,但没有资源读数:
#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使用开销。如果你需要尽可能小的内存使用量 - 你应该从文件加载
最后一个问题 - 如何通过编译器初始化它。没有现成的解决方案,但可以使用shape_predictor.h/deserialize函数中的代码并手动加载。我想,因为你不会得到较少的内存使用量相比,加载文件,这是坏的解决方案,
所以我的建议是从文件加载一个shape_predictor和全球范围内所有使用它的线程
什么是文件内容?它的结构是什么 –
@HumamHelfawi _shape_predictor_68_face_landmarks.dat_是使用[train_shape_predictor_ex.cpp](http://dlib.net/train_shape_predictor_ex.cpp.html)进行训练后的训练模型。它基本上是二进制文件。 – Mavie