是否有可能在编译时加载/读取shape_predictor_68_face_landmarks.dat? [英] Is it possible to load/read shape_predictor_68_face_landmarks.dat at compile time?

查看:6672
本文介绍了是否有可能在编译时加载/读取shape_predictor_68_face_landmarks.dat?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 DLIB中在 Visual Studio 中构建 C ++ face_landmark_detection_ex.cpp 。构建应用程序运行从命令promt和训练有素的模型和图像文件作为参数传递。

  face_landmark_detection_ex.exe shape_predictor_68_face_landmarks.dat图像。 jpg 

这个 shape_predictor_68_face_landmarks.dat 模型为68个地标对输入图像进行检测,每次运行时需要加载进行检测。我试图做以下事情。


  • 在构建应用程序或编译时加载这个 shape_predictor_68_face_landmarks.dat

  • 在代码中阅读 shape_predictor_68_face_landmarks.dat ,以便每次我的应用程序执行它时,都不会占用更多的内存。 b

    $ b

    有没有办法在我的应用程序中打包这个文件,这样会占用较少的物理内存。



    更新:

    如何储存 shape_predictor_68_face_landmarks.dat 文件,以便每次 shape_predictor 可以从这个缓冲区中读取数据。

    解决方案

    Visual Studio和没有t跨平台


    1. 您应该创建资源文件并将hape_predictor_68_face_landmarks.dat包含到您的项目中。请参阅 https://msdn.microsoft.com/ru-ru/library/7zxb70x7。 aspx 了解详情。这将使编译器把这个文件放到你的exe / dll中。

    2. 在运行时打开资源并获取内存指针 https://msdn.microsoft.com/zh-cn/library/windows/desktop /ee719660(v=vs.85).aspx


    3. 从指针创建内存流(std :: istream)。


      1. 使用dlib :: deserialize从此流反序列化


    这里是最小的例子,但没有资源阅读:

      #include< string> 
    #include< iostream>
    #include< dlib / image_processing / shape_predictor.h>

    $ b $ struct structuf:std :: streambuf {
    (char const * base,size_t size){
    char * p(const_cast< char *>(基础));
    this-> setg(p,p,p + size);
    }
    };
    struct imemstream:虚拟membuf,std :: istream {
    imemstream(char const * base,size_t size)
    :membuf(base,size)
    ,std :: istream static_cast< std :: streambuf>(this)){
    }
    };
    使用命名空间dlib; //重要的是要使用名称空间dlib反序列化正常工作
    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>缓冲区大小);
    if(fs.read(buffer.data(),size))
    {
    cout<< 成功读取<<大小<< 来自的字节<< file_name<< 进入缓冲区<< ENDL;
    imemstream stream(& buffer.front(),size); //这里我们从内存缓冲区加载。你可以改变这一行来使用Resource
    shape_predictor sp;
    反序列化(sp,stream);
    cout<< 反序列化shape_predictor<< ENDL;
    }
    else cout<< 无法阅读<< file_name<< 进入缓冲区<< ENDL;
    返回0;
    }

    关于内存使用情况。
    $ b $首先,你应该知道shape_predictor :: operator()是const,文档说对一个不同的线程使用一个shape_predictor是安全的。



    所以,你可以在程序开始时创建一个shape_predictor,并多次使用它,甚至从不同的线程中获取。

    接下来,将形状预测器放在资源中,将其加载到RAM程序启动时,但从资源反序列化将使该内存的副本,这将导致RAM使用开销。如果你需要尽可能少的内存使用量 - 你应该从文件加载它$ / b>

    最后一个问题 - 如何通过编译器初始化它。没有现成的解决方案,但可以使用shape_predictor.h / deserialize函数中的代码并手动加载。我认为,这是一个不好的解决方案,因为与加载文件相比,你不会得到更少的内存使用量。因此,我的建议是从文件加载一个shape_predictor并全局使用它所有线程


    I am trying to build a C++ application in Visual Studio using DLIB's face_landmark_detection_ex.cpp. The build application run from command promt and trained model and image file is passed as arguments.

    face_landmark_detection_ex.exe shape_predictor_68_face_landmarks.dat image.jpg
    

    this shape_predictor_68_face_landmarks.dat is the trained model for 68 landmarks to perform detection on input image and needs to load at run-time every time to perform any detection. I am trying to do following things.

    • Load this shape_predictor_68_face_landmarks.dat at building the application or compile time.
    • Read this shape_predictor_68_face_landmarks.dat inside the code so that every time my application strarts its execution, it will not take more amount of memory.

    Is there any way to pack this file inside my application so that it will take less physical memory to run.

    Update:

    How can I store this shape_predictor_68_face_landmarks.dat file in a static buffer so that every time shape_predictor can read from this buffer.

    解决方案

    Yes, its possible, but depends on Visual Studio and not cross-platform

    1. You should create resource file and include hape_predictor_68_face_landmarks.dat into your project. See https://msdn.microsoft.com/ru-ru/library/7zxb70x7.aspx for details. This will make compiler to put this file into your exe/dll

    2. Open resoure at runtime and get memory pointer https://msdn.microsoft.com/en-us/library/windows/desktop/ee719660(v=vs.85).aspx

    3. Create memory stream (std::istream) from pointer.

      1. deserialize from this stream with dlib::deserialize

    Here is minimal example, but without resource reading:

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

    And about memory usage.

    First of all you should know that shape_predictor::operator() is const, and the documentation says that is safe to use one shape_predictor for different threads.

    So, you can create one shape_predictor at the start of program and use it many times, even from different threads

    Next, putting shape predictor inside resource will make it be loaded into RAM when program starts, but deserializing it from resource will make copy of this memory, and this will lead to RAM usage overhead. If you need minimal possible RAM usage - you should load it from file

    And the last your question - how to initialize it by compiler. There is no ready-to-use solution for it, but you can use the code from shape_predictor.h/deserialize function and load it manually. I think, this is bad solution, because you will not get less RAM usage compared to loading file

    So my recommendation is to load one shape_predictor from file and use it globally for all threads

    这篇关于是否有可能在编译时加载/读取shape_predictor_68_face_landmarks.dat?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆