Сохранение и загрузка вектора<Mat> Qt & OpenCV
Я работаю над распознаванием лиц в Qt & openCV, используя распознаватель FisherFaces, который не поддерживает обновление, поэтому мне нужно сохранить базу данных лиц, чтобы переучить распознаватель после любых изменений.
Вот мой код для сохранения:
save(const std::vector* MatVect){
QFile file("students_dataset.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
QVector qimgvect;
for (size_t i = 0; i < MatVect->size(); ++i)
{
cv::Mat matt = MatVect->at(i);
QImage img((uchar*)matt.data, matt.cols, matt.rows, matt.step, QImage::Format_Indexed8);
qimgvect.push_back(img);
}
out << qimgvect ;
file.flush();
file.close();
}
и это для загрузки:
load(std::vector* MatVect)
{
QFile file("students_dataset.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
QVector qimgvect;
in >> qimgvect;
for (size_t i = 0; i < qimgvect.size(); ++i)
{
QImage img = qimgvect.at(i);
cv::Mat matt = cv::Mat(70, 70, CV_8U, img.bits(), img.bytesPerLine());
MatVect->push_back(matt);
}
file.close();
return;
}
проблема в том, что то, что я прочитал обратно из файла, не то, что я сохранил так что именно не так в этом коде (надеюсь, не во всем)?
Есть ли лучший / более простой способ сохранить вектор?
РЕДАКТИРОВАТЬ:
благодаря Marek_R часть преобразования исправлена, но теперь проблема заключается в сохранении и загрузке с помощью QDataStream:
так что вызывает эти строки?
РЕДАКТИРОВАТЬ:
Я попробовал это:
сделал QimgVect
public и elemenated часть QDataStream: MatVect-> QimgVect, чем QimgVect->MatVect, и она работала нормально, но после добавления QDataStream: MatVect-> QimgVect-> QDataStream и QDataStream->QimgVect->MatVect я получаю результат, показанный выше (вертикальный белые линии).
РЕДАКТИРОВАТЬ
преобразование изображения из RGB32 в Indexed8 после чтения из qdatastream дает следующий результат:
2 ответа
Так вот решение: для сохранения оттенков серого Qimage
через QDataStream
преобразовать его в Format_ARGB32
затем сохраните его, для загрузки конвертируйте обратно Format_Indexed8
: сохранение кода
QFile file("students_dataset.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
//converting to ARGB32
foreach (QImage img, qimgvect) {
img = img.convertToFormat(QImage::Format_ARGB32);
}
// saving to QDataStream
out << qimgvect ;
file.flush();
file.close();
для загрузки
QFile file("students_dataset.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
QVector<QImage> qimgvect;
// loading images vector from QDatastream
in >> qimgvect;
// converting to grayscale
QVector<QRgb> grayscale;
for (int i = 0; i < 256; ++i) grayscale.append(qRgb(i, i, i));
for (int i, i < qimgvect.size(),i++) {
QImage img = qimgvect.at(i).convertToFormat(QImage::Format_Indexed8,grayscale);
qimgvect.push_back(img);
}
file.close();
Я думаю, что даже QImage
с другими форматами столкнется с той же проблемой, так как предполагается, что формат по умолчанию Format_ARGB32
Это проблема управления памятью. При создании матрицы из куска памяти копия этой памяти не создается. В то же время эта память удаляется, когда QImage
выходит за рамки.
Проверьте ответ о конвертации между QImage
а также cv:Mat
(есть лучшая ссылка в комментарии, но по какой-то причине страница не работает, поэтому я не предоставил эту ссылку здесь).
Когда вы справляетесь cv::Mat
создается только поверхностная копия. Фактическое содержание матрицы не копируется. Увидеть cv::Mat
конструкторская документация:
m - Массив, который (полностью или частично) присваивается построенной матрице. Данные конструкторы не копируются. Вместо этого создается заголовок, указывающий на m данных или его подмассив и связанный с ним. Счетчик ссылок, если есть, увеличивается. Таким образом, когда вы модифицируете матрицу, сформированную с помощью такого конструктора, вы также модифицируете соответствующие элементы m. Если вы хотите иметь независимую копию подмассива, используйте
Mat::clone()