2017-01-22 304 views
0

イメージディスクリプタ(OpenCV SIFTまたはVLFeat Dense SI FTなど)が一連のイメージのディスクリプタを計算する方法を書きました(std::vector<std::string> filesに保存)。記述子は、ComputeDescriptors(image, descriptorMatrix)によって呼び出され、descriptorMatrixから計算された記述子が入ります。release()を呼び出してもcv :: Matメモリが解放されない?

次に、samples(通常50個)の記述子をランダムに選択し、std::vector<cv::Mat1f> descriptorssampledDescriptors行列を押します。

これはコードである:

void SIFTDescriptor::ComputeDescriptorsRange(const std::vector<std::string> &files, std::vector<cv::Mat1f> &descriptors){ 
    cv::Mat1f imgDescriptors; 
    cv::Mat img; 
    for(int i=0 ; i<files.size() ; i++){ 
     std::cout<<"Describing "<<files[i]<<std::endl; 
     img = cv::imread(files[i], cv::IMREAD_GRAYSCALE); 
     if(!img.data) 
      //throw error 
     //resoze dim is a class member 
     if(resizeDim>0) 
      ImgUtility::resize(img,resizeDim); 
     ComputeDescriptors(img,imgDescriptors); 
     if(samples > 0 && samples < imgDescriptors.rows){ 
      std::cout<<"Sampling "<<imgDescriptors.rows<<" descriptors..."<<std::endl; 
      cv::Mat1f sampledDescripotrs; 
      std::vector<int> v(imgDescriptors.rows); 
      std::iota (std::begin(v), std::end(v), 0); //fill v with 0 ... imgDescriptors.rows 
      std::random_device rd; 
      std::mt19937 g(rd()); 
      std::shuffle(v.begin(), v.end(), g); 
      for(int j=0 ; j<samples; j++){ 
       sampledDescripotrs.push_back(imgDescriptors.row(v[j])); 
      } 
      descriptors.push_back(sampledDescripotrs); 
      sampledDescripotrs.release(); 
     } 
     else 
      descriptors.push_back(imgDescriptors); //copy of a smart pointer, not expensive 
     imgDescriptors.release(); 
     std::cout<<"descriptors["<<i<<"]="<<descriptors[i].rows<<std::endl; 
     std::cout<<descriptors[i]<<std::endl; 
    } 

。これは特に、そのような記述子の数千が抽出されるVLFeat Dense SIFTとして稠密記述子ため、メモリ効率的に行われます。数千の画像で私たちはすぐにメモリを使い果たすでしょう。代わりに、このソリューションを使用して、イメージごとに50の記述子しか保持しません(これは私のトレーニングには十分です)。

しかし、いくつかの奇妙な理由で、OpenCV SIFTを使用すると大きなメモリ使用率はありませんが、VLFeat Dense SIFTを使用すると、どちらの場合でもsamplesが等しい場合でもメモリはかなり高速になります!

私の唯一の説明は、(cv::Mat1fちょっとスマートポインタであるので、ループの終わりに自分自身を解放すべきであるためであるが、いずれにせよ必要ではないであるべきである)、各ループでimgDescriptorsによって使用されるメモリが解放されないことであってもimgDescriptorsを使用してしかし、私はこれがどのように可能か理解していません。

これはVLFeatで密SIFTためComputeDescriptorコードです:

void DSIFTVLFeat::ComputeDescriptors(cv::Mat &img, cv::Mat1f &descriptors){ 
    descriptors.release(); 

    // transform image in cv::Mat to float vector 
    cv::Mat imgFloat; 
    img.convertTo(imgFloat, CV_32F, 1.0/255.0); 
    if(!imgFloat.isContinuous()) 
     throw std::runtime_error("imgFloat is not continous"); 

    for(int i=binSize; i<=maxBinSize; i+=2){ 
     VlDsiftFilter *dsift = vl_dsift_new_basic (img.rows, img.cols, step, i); 
     vl_dsift_process (dsift, imgFloat.ptr<float>()); 
     cv::Mat scaleDescs(vl_dsift_get_keypoint_num(dsift), 128, CV_32F, (void*) vl_dsift_get_descriptors(dsift)); 
     descriptors.push_back(scaleDescs); 
     scaleDescs.release(); 
     free(dsift); 
    } 
} 

答えて

0

私は自分で問題を見つけた:どうやらfree(dsift)作成された記述子を、割り当て解除されませんので、私は、ヒープ上に積み重ねられましたそれらを解放することなく。

代わりにvl_sift_delete(dsift)が問題を解決したようです。

関連する問題