Ask Your Question
0

Loading cv::RTrees from memory

asked 2013-05-20 07:26:13 -0600

voidmain gravatar image

I use OpenCv for image classification. After training I've saved model to *.yaml.gz. Then I've added this file to embedded resources. Now I need to load model from resource, but OpenCv allows only loading from files or strings.

HMODULE ModuleHandle;

void LoadBinaryResource(int resId, void** data, int& size)
{
    HRSRC resource = ::FindResource(ModuleHandle, MAKEINTRESOURCE(resId), RT_RCDATA);
    HGLOBAL resourceData = ::LoadResource(ModuleHandle, resource);
    *data = ::LockResource(resourceData);
    size = ::SizeofResource(ModuleHandle, resource);
}


void LoadRTreesFromResource(int resId, cv::RTrees& forest)
{
    void* binaryData;
    int size;
    LoadBinaryResource(resId, &binaryData, size);

    // here I need to load CvStatModel from binaryData
}

Now I am forced to write data to a file and then use cv::RTres::load method.

Is there any way to load CvStatModel from memory? Or how can I serialize/deserialize model to binary format without using methods cv::RTres::save and cv::RTres::load?

Thank you!

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2013-05-22 11:19:38 -0600

voidmain gravatar image

Probably the only solution is to uncompress data using zLib manually...

void LoadBinaryResource(int resId, void** data, int& size)
{
    HRSRC resource = ::FindResource(ModuleHandle, MAKEINTRESOURCE(resId), RT_RCDATA);
    HGLOBAL resourceData = ::LoadResource(ModuleHandle, resource);
    *data = ::LockResource(resourceData);
    size = ::SizeofResource(ModuleHandle, resource);
}

std::string LoadForestData(int resId)
{
    void* compressedData;
    int compressedDataSize;
    LoadBinaryResource(resId, &compressedData, compressedDataSize);

    std::string uncompressedData;

    const int bufferSize = 1024*1024;
    char* buffer = new char[bufferSize];

    z_stream strm  = {0};
    strm.total_in  = strm.avail_in  = compressedDataSize;
    strm.next_in   = (Bytef*)compressedData;

    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    int ret = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib

    if(ret != Z_OK) {
        throw std::exception("Invalid forest");
    }

    do {
        strm.avail_out = bufferSize;
        strm.next_out = (Bytef *)buffer;
        ret = inflate(&strm, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
        switch (ret) {
            case Z_NEED_DICT:
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                inflateEnd(&strm);
                throw std::exception("Invalid forest");
        }
        int have = bufferSize - strm.avail_out;

        uncompressedData.insert(uncompressedData.end(), &buffer[0], &buffer[have]);
    }
    while(ret != Z_STREAM_END);
    inflateEnd(&strm);

    delete[] buffer;

    return uncompressedData;
}


void ReadForest(cv::RandomTrees& forest, int resId)
{
    std::string forestData = LoadForestData(resId);

    CvFileStorage* fs = cvOpenFileStorage(forestData.c_str(), NULL, CV_STORAGE_READ | CV_STORAGE_MEMORY);

    CvFileNode* model_node = 0;
    CvFileNode* root = cvGetRootFileNode( fs );
    if(root->data.seq->total > 0) {
        model_node = (CvFileNode*)cvGetSeqElem( root->data.seq, 0 );
    }
    forest.read(fs, model_node);
}
edit flag offensive delete link more

Question Tools

Stats

Asked: 2013-05-20 07:26:13 -0600

Seen: 446 times

Last updated: May 22 '13