问题
I'm working on face recognition in Qt & openCV using the FisherFaces recognizer which doesn't support updating so i have to save the faces database to retrain the recognizer after any changes.
Here is my code for saving :
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();
}
and this is for loading :
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;
}
the problem is that what I read back from the file is not what i savedso what's exactly wrong in this code (hope not all of it ) ?
is there a better/easier way of saving the vector ?
EDIT :
thanks to Marek_R the conversion part is fixed, but saving and loading with QDataStream is the problem now :
so what's causing those lines ?
EDIT :
I have tried this :
made
QimgVect
public and elemenated QDataStream part : MatVect-> QimgVect than QimgVect->MatVect and it did work fine, but after adding QDataStream : MatVect-> QimgVect->QDataStream and QDataStream->QimgVect->MatVect i get get the result shown above( vertical white lines ).EDIT
converting the image from RGB32 to Indexed8 after reading from qdatastream gives the following result :
回答1:
this is memory management issue. When you create matrix from piece of memory copy of this memory is not created. At the same time this memory is disposed when QImage
goes out of the scope.
Check answer about converting between QImage and cv:Mat (there is a better link in comment but for some reason page is not working so I didn't provided this link here).
When you are coping cv::Mat
only a shallow copy is created. Actual Matrix contents is not copied. See cv::Mat constructor documentation:
m – Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied by these constructors. Instead, the header pointing to m data or its sub-array is constructed and associated with it. The reference counter, if any, is incremented. So, when you modify the matrix formed using such a constructor, you also modify the corresponding elements of m . If you want to have an independent copy of the sub-array, use
Mat::clone()
回答2:
SO Here is a solution :
for saving grayscale Qimage
through QDataStream
convert it to Format_ARGB32
then save it, for loading convert it back to Format_Indexed8
:
saving code
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();
for loading
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();
I think even QImage
with other Formats will face the same problem since it is assumed that the default format is Format_ARGB32
来源:https://stackoverflow.com/questions/26073613/saving-and-loading-vectormat-qt-opencv