保存和加载矢量<mat> Qt&amp; OpenCV的</垫>

时间:2014-09-27 10:17:37

标签: qt opencv mat qimage qdatastream

我在Qt&amp; amp; openCV使用FisherFaces识别器,它不支持更新,所以我必须保存faces数据库,以便在任何更改后重新训练识别器。
这是我保存的代码:        

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;
    } 
问题是我从文件中读回的不是我保存的内容 saved loaded

那么这段代码究竟出了什么问题(希望不是全部)? 是否有更好/更简单的方法来保存向量?
编辑:
感谢 Marek_R ,转换部分已修复,但现在保存和加载QDataStream是问题:
saved loaded
是什么导致这些线?
编辑:
我试过这个:
使QimgVect公共和最终的QDataStream部分: MatVect-&gt; QimgVect QimgVect-&gt; MatVect 并且它确实工作正常,但在添加QDataStream之后: MatVect-&gt; QimgVect-&gt; QDataStream QDataStream-&gt; QimgVect-&gt; MatVect 我得到上面显示的结果(垂直白线)。
修改
从qdatastream读取后,将图像从 RGB32 转换为 Indexed8 会产生以下结果:
enter image description here

2 个答案:

答案 0 :(得分:1)

这是内存管理问题。当您从内存块创建矩阵时,不会创建此内存的副本。同时,当QImage超出范围时,将释放此内存。

检查有关converting between QImage and cv:Mat的答案(评论中有更好的链接但由于某种原因页面无效,所以我在此处未提供此链接。)

当你处理cv::Mat时,只创建一个浅拷贝。不复制实际矩阵内容。见cv::Mat constructor documentation

  

m - 将(作为整体或部分)分配给构造矩阵的数组。 这些构造函数不会复制任何数据。   而是构造指向m数据或其子数组的头   并与之相关联。参考计数器(如果有)递增。   所以,当你修改使用这样的构造函数形成的矩阵时,你   还修改了m的相应元素。 如果你想要一个   子阵列的独立副本,使用Mat::clone()

答案 1 :(得分:0)

SO这是一个解决方案: 要保存灰度QimageQDataStream,请将其转换为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