Flann descriptor save and load doesn't work

asked 2014-05-27 16:26:53 -0500

puneetdabulya gravatar image

updated 2014-05-28 09:50:27 -0500

berak gravatar image
void testSaveAndLoad(Mat descriptors, string outputFile) {
    vector<string> images;

    flann::LshIndexParams lshIndexParams(20,10,2);
    flann::Index kdtree(descriptors, lshIndexParams, cvflann::FLANN_DIST_HAMMING);

    cout << "outputting index file to disk: " << "\n";

    // just to check whether loaded ones are same or similar    
    writeMatToFile(descriptors, "before_save.dat");
    kdtree.save(outputFile);

    // saving done .. now load
    Mat mat = Mat(descriptors.rows, descriptors.cols, CV_8UC1);

    // read saved indices
     flann::Index kdtree1(mat,
                        flann::SavedIndexParams(outputFile), cvflann::FLANN_DIST_HAMMING);

   writeMatToFile(mat, "after_save.dat");

    cout << "Loaded mat of size " << mat.rows << " " << mat.cols << "\n";

    // prepare to output indices and distances
    Mat indices = Mat(descriptors.rows, 2, CV_32S);
    Mat dists = Mat(descriptors.rows, 2, CV_32S);
    kdtree1.knnSearch(descriptors, indices, dists, 2);
 }

before_save.dat:

%YAML:1.0
mat: !!opencv-matrix
   rows: 6342
   cols: 61
   dt: u
   data: [ 1, 0, 140, 7, 1, 238, 55, 0, 0, 0, 0, 0, 0, 0, 0, 128, 25,
       122, 134, 6, 0, 0, 240, 248, 227, 1, 3, 227, 249, 255, 62, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 24, 0, 0, 128, 48, 230, 15, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 128, 25, 59, 243, 51, 6, 16, 64, 252, 255, 199, 16, 255,
       7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 6, 0, 60, 0, 0, 0, 0, 0, 0,
       0, 0, 192, 14, 160, 3, 112, 0, 7, 16, 0, 0, 0, 0, 0, 0, 254, 63,
.........



after_save.dat:

%YAML:1.0
mat: !!opencv-matrix
   rows: 6342
   cols: 61
   dt: u
   data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
.......

And knnSearch throws segfaults during the matching.

Thanks

edit retag flag offensive close merge delete

Comments

1

imho, there's little a flaw in your democode:

flann::Index kdtree1(mat,
                    flann::SavedIndexParams(outputFile), cvflann::FLANN_DIST_HAMMING);

see, mat there is an InputArray only, you can't expect it to update, so saving it after constructing the index does not make any sense.

(it still crashes in knnSearch)

berak gravatar imageberak ( 2014-05-28 06:40:43 -0500 )edit

Yes I agree. That was another issue with this API. How can they expect user to know the size of Mat without loading that file. The API should take care of this. Temporary fix is :

#include "opencv2/flann/saving.h"

FILE* fin = fopen(outputFile.c_str(), "rb");
if (fin == NULL)
    return false;

IndexHeader header = load_header(fin);

int dataType = header.data_type == FLANN_UINT8 ? CV_8U :
header.data_type == FLANN_INT8 ? CV_8S :
header.data_type == FLANN_UINT16 ? CV_16U :
header.data_type == FLANN_INT16 ? CV_16S :
header.data_type == FLANN_INT32 ? CV_32S :
header.data_type == FLANN_FLOAT32 ? CV_32F :
header.data_type == FLANN_FLOAT64 ? CV_64F : -1;

Mat mat = Mat(header.rows, header.cols, dataType);
puneetdabulya gravatar imagepuneetdabulya ( 2014-05-28 12:24:13 -0500 )edit

Linked bug and temporary fix: http://code.opencv.org/issues/3720

puneetdabulya gravatar imagepuneetdabulya ( 2014-05-28 18:59:42 -0500 )edit