イメージディスクリプタ(OpenCV SIFTまたはVLFeat Dense SI FTなど)が一連のイメージのディスクリプタを計算する方法を書きました(std::vector<std::string> files
に保存)。記述子は、ComputeDescriptors(image, descriptorMatrix)
によって呼び出され、descriptorMatrix
から計算された記述子が入ります。release()を呼び出してもcv :: Matメモリが解放されない?
次に、samples
(通常50個)の記述子をランダムに選択し、std::vector<cv::Mat1f> descriptors
のsampledDescriptors
行列を押します。
これはコードである:
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);
}
}