Search code examples
c++opencvfile-storageorbfeature-descriptor

opecv c++ matching descriptors from file


I extract descriptors and then save them to file like this:

detector->detect(img, imgKpts);
extractor->compute(img, imgKpts, imgMat);
fsKpts << filename << imgMat;

but when I read them back again like this:

std::vector<cv::Mat> filesDVec;
cv::Mat temp;
fs[filename] >> temp;
filesDVec.push_back(temp);

and match the descriptors with a loaded in image:

cv::Mat givenIn, givenInMat;
givenIn = cv::imread(dataDirGivenIn, CV_LOAD_IMAGE_GRAYSCALE);
cv::vector<cv::KeyPoint> givenInKpts;
detector->detect(givenIn, givenInKpts);
extractor->compute(givenIn, givenInKpts, givenInMat);
cv::vector<cv::DMatch> matchesVector;

with the 2 cv::Mats this way round:

matcher->match(filesDVec[i], givenInMat, matchesVector);

A.K.A match(Scene, Object, ...) the output is: minDist = 100 maxDist = 0 (not a single match).

But with them this way round:

matcher->match(givenInMat, filesDVec[i], matchesVector);

A.K.A match(Object, Scene, ...) this error is thrown:

opencv error:assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type = CV_8U)) in void cv::batchDistance

I want to have the descriptive information from each image saved so it can be loaded in, what am I doing wrong?

Edit

I would add that it is not a case of trying to match and image to itself as it is known that the matcher does not work if object and source image are equal for testing purposes.

Edit 2

Contents of file:

Image_0: !!opencv-matrix
   rows: 315
   cols: 32
   dt: u
   data: [ 0, 128, 196, 159, 108, 136, 172, 39, 188, 3, 114, 16, 172,
       234, 0, 66, 74, 43, 46, 128, 64, 172, 67, 239, 4, 54, 218, 8, 84,
       0, 225, 136, 160, 133, 68, 155, 204, 136, 232, 47, 61, 17, 115,
       18, 236, 106, 8, 81, 107, 131, 46, 128, 114, 56, 67, 213, 12, 50,
       218, 64, 21, 8, 209, 136, 180, 69, 70, 142, 28, 130, 238, 96, 141,
       128, 243, 2, 74, 74, 37, 65, 120, 161, 78, 226, 104, 163, 0, 204,
...
etc

Read:

std::vector<cv::Mat> filesDVec(imgVec.size());
cv::Mat temp;
cv::FileStorage fs("tileDesc.yml", cv::FileStorage::READ);
for(size_t i = 0; i < (imgVec.size()); i++){
    cv::string iValue = std::to_string(i);
    cv::string filename = "Image_" + iValue;
    fs[filename] >> temp;
    filesDVec.push_back(temp);  
}
fs.release();

Solution

  • The problem is that you allocate and construct filesDVec with imgVec.size() elements (they are empty cv::Mats). Then every descriptor (you load in the for loop) will be added at the end of the vector filesDVec.

    As a result of this you try to match some empty cv::Mat to givenInMat and most likely it will result in the application crash or assert. Try to read it as below:

    std::vector<cv::Mat> filesDVec;
    cv::Mat temp;
    cv::FileStorage fs("tileDesc.yml", cv::FileStorage::READ);
    
    for(size_t i = 0; i < (imgVec.size()); i++){
        cv::string iValue = std::to_string(i);
        cv::string filename = "Image_" + iValue;
        fs[filename] >> temp;
        filesDVec.push_back(temp);  
    }
    
    fs.release();