Я пытаюсь воссоздать объект Mat с данными, хранящимися в базе данных SQLite. Я открываю изображение, получаю его дескрипторы (используя Surf), а затем сохраняю данные в SQLite DB. После этого я пытаюсь прочитать эти данные из БД и воссоздать один и тот же объект Mat с этими данными.
Это моя таблица:
create table images(
id INTEGER,
descriptors BLOB
);
Это получить дескрипторы и сохранить их в части БД:
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);
И вот как я извлекаю данные из БД:
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;
}
Проблема состоит в том, что эти данные (в основном массив, char *, которые являются данными, возвращаемыми методами sqlite) состоят из подписанных значений (я проверил оба значения в БД с помощью клиента БД и значения char массив, полученный от чтения базы данных, и они верны). Однако при создании объекта Mat эти значения, похоже, преобразуются в неподписанные числа, поэтому значения Mat неверны.
Вот краткое изложение того, что я намереваюсь сделать, и мою проверку сохраненных значений на каждом шаге:
Конструктор Mat, который я использую, следующий:
TempMat = cv::Mat(height, width, CV_32F, buffer);
Я использую CV_32F, потому что тот тип, который я получаю при проверке после получения дескрипторов (я получаю тип 5, который я нашел, это CV_32F).
Я попытался изменить тип мата и вставить значения вручную в объект Mat, но ничего не работает (или я не знаю, как заставить его работать). Есть ли способ построения объекта Mat с подписанными данными?
Ну, проблема решена. Похоже, что речь идет о решении двух разных вопросов:
Во-первых, по какой-то причине создание матрицы напрямую с помощью типа CV_32F (тип, который я использую для распознавания SURF) создаст его со значениями в неправильном порядке. Я не знаю, почему, я искал несколько источников, и я начинаю верить этому в ошибку. Я даже попробовал простые примеры (создание матрицы 2x2 и добавление значений вручную), и это просто не сработало (значения не закончились там, где я сказал им идти). Это было решено путем создания матрицы с использованием типа CV_64F, а затем преобразования ее в CV_32F:
Mat m = Mat(h,w,CV_64F);
fillValues(...);
m.convertTo(m,CV_32F);
Другая проблема заключалась в том, что похоже, что данные, которые я предоставлял конструктору матрицы, находятся в неправильном формате. После решения первой проблемы цифры, похоже, не читали правильно (они оказались там, где они были, но они были изменены), поэтому я пробовал разные подходы. Преобразование массива символов в двойной вектор и добавление значений вручную один за другим - это то, что я придумал, и он работает:
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;
}
}
}
После включения обоих этих исправлений проблема была решена - обновленная матрица была идентична той, которая была создана в первую очередь (и хранилась в базе данных SQLite).
buffer
и код, который проверяет загрузку.