2013-05-16 31 views
3

我使用OpenCv進行圖像分類。訓練完成後,我將模型保存到* .yaml.gz。然後我將這個文件添加到嵌入式資源。現在我需要從資源加載模型,但OpenCv只允許從文件或字符串加載。從內存中加載cv :: RTrees

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 
} 

現在我被迫將數據寫入文件,然後使用cv :: RTres :: load方法。

有什麼辦法從內存中加載CvStatModel?或者我怎麼能序列化/反序列化模型爲二進制格式而不使用方法cv :: RTres :: save和cv :: RTres :: load?

謝謝!

回答

1

大概是唯一的解決辦法是使用ZLIB手動...

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); 
} 
解壓數據