C ++ OpenCV создает Mat из массива символов SIGNED (без знака)

0

Я пытаюсь воссоздать объект 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 неверны.

Вот краткое изложение того, что я намереваюсь сделать, и мою проверку сохраненных значений на каждом шаге:

  1. Получить дескрипторы изображений - ОК
  2. Храните их в БД - ОК
  3. Прочтите их из БД - ОК
  4. Создайте Mat с ними и увидите значения Mat - WRONG

Конструктор Mat, который я использую, следующий:

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

Я использую CV_32F, потому что тот тип, который я получаю при проверке после получения дескрипторов (я получаю тип 5, который я нашел, это CV_32F).

Я попытался изменить тип мата и вставить значения вручную в объект Mat, но ничего не работает (или я не знаю, как заставить его работать). Есть ли способ построения объекта Mat с подписанными данными?

  • 1
    Откуда вы знаете, что он конвертируется в числа без знака? Вам нужно показать код, который создает buffer и код, который проверяет загрузку.
  • 0
    Будем распечатывать результаты и сравнивать их. Я действительно не знаю, что происходит в конструкторе, но, по-видимому, он работает с беззнаковыми символами, и после печати я вижу только положительные числа (раньше были положительные и отрицательные числа), поэтому я предполагаю, что это происходит. Я отредактирую пост с некоторыми фрагментами кода.
Показать ещё 2 комментария
Теги:
opencv
char
signed
mat

1 ответ

-1
Лучший ответ

Ну, проблема решена. Похоже, что речь идет о решении двух разных вопросов:

Во-первых, по какой-то причине создание матрицы напрямую с помощью типа 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).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню