C++ OpenCV create Mat from SIGNED char array (not unsigned)

2k Views Asked by At

I'm trying to recreate a Mat object with data stored in an SQLite database. I open an image, get its descriptors (using Surf), then store the data in the SQLite DB. After that, I try to read that data from the DB and recreate the same Mat object with that data.

This is my table:

create table images(
    id INTEGER,
    descriptors BLOB
);

This is the get the descriptors & store them in the DB part:

Mat image;
vector<KeyPoint> keypoints;
image = imread(nameImage,0);  
SurfFeatureDetector surf(500);
surf.detect(image, keypoints);
SurfDescriptorExtractor surfDesc;
Mat descriptors, descriptors;
surfDesc.compute(image, keypoints, descriptors);
string command = "insert into images values(" << id << ",'" << descriptors << "');";
sqlite3_exec(db, command, callback, (void*)data, &errMsg);

And this is how I get the data out of the DB:

string command = "select id, descriptors from images;";
sqlite3_exec(db, command, callback, (void*)data, &errMsg);

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
    int id = atoi(argv[0]);
    /*argv[1] contains the matrix data and it is untouched, the fun begins */
    /*when I try to put that data into a Mat object: */
    Mat currentDescriptors;
    currentDescriptors = Mat(h,w,CV_16S,argv[1]);
    /*after this, the Mat data gets borked /*
    return 0;
}

The problem is, this data (basically an array, char*, which is the data returned by the sqlite methods) is composed of signed values (I've checked both the values in the DB using a DB client and the values of the char array obtained from reading the database and they are correct). However, when creating the Mat object, these values seem to convert to unsigned numbers, so the Mat values are wrong.

Here's a summary of what I intend to do and my checking of the stored values at each step:

  1. Get image descriptors - OK
  2. Store them in the DB - OK
  3. Read them from the DB - OK
  4. Create a Mat with them and see the Mat's values - WRONG

The Mat constructor i'm using is the following one:

TempMat = cv::Mat(height, width, CV_32F, buffer);

I'm using CV_32F because that's the type that I get when checking it after getting the descriptors (I get type 5, which I found is CV_32F).

I've tried changing the mat type and inserting the values manually into the Mat object, but nothing seems to work (or I do not know how to make it work). Is there any way of constructing a Mat object with signed data?

1

There are 1 best solutions below

0
On BEST ANSWER

Well, problem solved. It looks like it was a matter of solving two different issues:

First, for some reason creating the matrix directly with CV_32F type (the type I'm using for SURF recognition) will create it with the values in a wrong order. I don't know why, I've searched several sources and I'm starting to believe it's a bug. I even tried simple examples (creating a 2x2 matrix and adding values manually) and it just didn't work (values didn't end up where I told them to go). This was solved by creating the matrix using the CV_64F type, and then converting it to CV_32F:

Mat m = Mat(h,w,CV_64F);
fillValues(...);
m.convertTo(m,CV_32F);

The other problem was it looks like the data I was providing the matrix constructor is in a wrong format. After solving the first problem, the numbers didn't seem to be getting read properly (they ended up where they had to, but they were changed), so I tried different approaches. Converting the char array to a double vector and inserting the values manually one by one is what I came up with, and it works:

vector<double> fvalues;
int position = 0;
for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
        if(position!=fvalues.size()){
            currentDescriptors.at<double>(i,j)=fvalues.at(position);
            position++;
        } else {
            break;
        }
    }
}

After including both of these fixes the problem was solved - the recreated matrix was identical to the one created in the first place (and stored in the SQLite database).