Как записать плавающий коврик в файл в OpenCV

У меня есть матрица

Mat B(480,640,CV_32FC1);

содержащие плавающие значения ... Я хочу записать эту матрицу в файл, который можно открыть в блокноте, MS Word или Excel, чтобы увидеть значения внутри и для хранения .... функция imwrite может сохранять только 8-битные или 16-битные изображения.

Напишите свои предложения, если это можно сделать ?? если да, то как ??


person Karthik Murugan    schedule 01.05.2013    source источник
comment
вы можете [записать матрицу в файл xml или yaml] [1]. [1]: stackoverflow.com/questions/15115046/   -  person Saikat    schedule 01.05.2013
comment
см. лучший ответ ИМХО   -  person sturkmen    schedule 28.08.2018


Ответы (5)


Использование чистых вызовов API OpenCV:

// Declare what you need
cv::FileStorage file("some_name.ext", cv::FileStorage::WRITE);
cv::Mat someMatrixOfAnyType;

// Write to file!
file << "matName" << someMatrixOfAnyType;

Расширение файла может быть xml или yml. В обоих случаях вы получаете небольшой заголовок, который можно легко удалить / проанализировать, после чего у вас будет доступ к данным в формате с плавающей запятой. Я успешно использовал этот подход (с файлами yml) для получения данных в Matlab и Matplotlib.

Чтобы получить данные:

  1. открыть файл любым редактором
  2. затем подавите весь текст и числа, кроме содержимого тега данных (т. е. значений пикселей).
  3. Когда закончите, сохраните файл с расширением txt или csv и откройте его с помощью Matlab (работает перетаскивание).

Вуаля. Возможно, вам придется изменить форму полученной матрицы в командной строке Matlab, если она неправильно угадывает размер изображения.

person sansuiso    schedule 01.05.2013
comment
Спасибо ... Я могу открыть файл с помощью gedit .. Вы можете мне сказать, как загрузить этот xml-файл в Matlab или Excel ??? .. - person Karthik Murugan; 01.05.2013
comment
Я думаю, вам нужно дать матрице имя, например file << "matName" << someMatrixOfAnyType; в противном случае я получаю эту ошибку: OpenCV Error: Unspecified error (No element name has been given) in operator<<, file /usr/local/include/opencv2/core/operations.hpp, line 2910 - person Daniel Golden; 17.10.2014
comment
Да, ты прав. Без имени файл yml плохо сформирован (перед данными отсутствует разметка). - person sansuiso; 17.10.2014
comment
За ним должно следовать file.release(). Как правило, хорошо закрывать и освобождать ресурсы для любого ввода-вывода файла. - person dev_nut; 20.04.2015
comment
@dev_nut: деструктор FileStorage вызывает release (), нет необходимости вызывать его явно. - person hauron; 27.09.2015
comment
Как после сохранения в файл загрузить сохраненную матрицу? - person Will Andrew; 07.12.2015
comment
Нашел это: stackoverflow.com/questions/19200844/ - person Will Andrew; 07.12.2015
comment
opencv также поддерживает json - person Ohad Cohen; 30.11.2017
comment
Привет, какая версия Python для этого? не могли бы вы дать какую-нибудь подсказку? - person Scott Yang; 15.12.2018

Вы можете записать cv::Mat в текстовый файл, используя простую обработку файлов C ++.

Вот как это сделать:

#include <iostream>
#include <fstream>

using namespace std;

void writeMatToFile(cv::Mat& m, const char* filename)
{
    ofstream fout(filename);

    if(!fout)
    {
        cout<<"File Not Opened"<<endl;  return;
    }

    for(int i=0; i<m.rows; i++)
    {
        for(int j=0; j<m.cols; j++)
        {
            fout<<m.at<float>(i,j)<<"\t";
        }
        fout<<endl;
    }

    fout.close();
}

int main()
{
    cv::Mat m = cv::Mat::eye(5,5,CV_32FC1);

    const char* filename = "output.txt";

    writeMatToFile(m,filename);

}
person sgarizvi    schedule 01.05.2013
comment
Хочу принять и этот ответ ... Но можно дать только 1 ... в любом случае, этот простой подход тоже отлично работает! 1 - person Karthik Murugan; 01.05.2013
comment
@smttsp Я так не думаю. Реализация OpenCV может быть оптимизирована. - person sgarizvi; 07.10.2013
comment
Спасибо, я подозревал, что оптимизация компилятора может сделать оба подхода с одинаковой скоростью. - person smttsp; 07.10.2013
comment
Я проверил оба ответа, и ваш ответ на 50-60% медленнее, чем другой ответ для двойной матрицы 1024x1024, записываемой в файл xml. - person smttsp; 07.10.2013
comment
@smttsp ... Да, конечно, мое решение - это просто базовый подход. Хотя реализация OpenCV гораздо более оптимизирована. - person sgarizvi; 07.10.2013
comment
@sgarizvi, ваше решение более полезно для пакетной обработки по сравнению с принятым ответом. Если нам нужно записать в файлы сотни объектов cv :: mat, будет сложно открывать и изменять каждый файл xml / yml, как это предлагается в принятом ответе, если мы снова не напишем код для автоматического изменения. - person Ruchir; 30.07.2015

OpenCV может сериализовать (сохранять) свои объекты в форматах JSON, XML или YAML. Вы можете использовать любые редакторы, которые понимают эти форматы, чтобы читать эти файлы, или использовать OpenCV для загрузки данных (десериализации) из этих файлов. Подробное объяснение того, как это делается, можно найти здесь. Короче говоря, чтобы сохранить данные в xml-файле, вы должны вызвать

cv::FileStorage fs("/path/to/file.xml", cv::FileStorage::WRITE); // create FileStorage object
cv::Mat cameraM; // matrix, which you need to save, do not forget to fill it with some data
fs << "cameraMatrix" << cameraM; // command to save the data
fs.release(); // releasing the file.

Если вы хотите использовать JSON или YAML, просто измените расширение на .json или .yaml/.yml - openCV автоматически поймет ваши намерения.

Главное - это команда

fs << "cameraMatrix" << cameraM;

строка "cameraMatrix" - это имя тега, под которым эта матрица будет храниться и с помощью которого эту матрицу можно будет найти позже в файле.

Обратите внимание, что формат xml не позволит вам использовать имена тегов с пробелами и некоторыми специальными символами, поскольку разрешены только буквенно-цифровые значения, точки, дефисы и подчеркивания (подробности см. В спецификации XML), а в YAML и JSON вы можете иметь что-то вроде

fs << "Camera Matrix" << cameraM;
person John Smith    schedule 07.11.2018

Я написал такой код:

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

/*
Will save in the file:
cols\n
rows\n
elemSize\n
type\n
DATA
*/
void serializeMatbin(cv::Mat& mat, std::string filename){
    if (!mat.isContinuous()) {
        std::cout << "Not implemented yet" << std::endl;
        exit(1);
    }

    int elemSizeInBytes = (int)mat.elemSize();
    int elemType        = (int)mat.type();
    int dataSize        = (int)(mat.cols * mat.rows * mat.elemSize());

    FILE* FP = fopen(filename.c_str(), "wb");
    int sizeImg[4] = {mat.cols, mat.rows, elemSizeInBytes, elemType };
    fwrite(/* buffer */ sizeImg, /* how many elements */ 4, /* size of each element */ sizeof(int), /* file */ FP);
    fwrite(mat.data, mat.cols * mat.rows, elemSizeInBytes, FP);
    fclose(FP);
}

cv::Mat deserializeMatbin(std::string filename){
    FILE* fp = fopen(filename.c_str(), "rb");
    int header[4];
    fread(header, sizeof(int), 4, fp);
    int cols            = header[0]; 
    int rows            = header[1];
    int elemSizeInBytes = header[2];
    int elemType        = header[3];

    //std::cout << "rows="<<rows<<" cols="<<cols<<" elemSizeInBytes=" << elemSizeInBytes << std::endl;

    cv::Mat outputMat = cv::Mat::ones(rows, cols, elemType);

    size_t result = fread(outputMat.data, elemSizeInBytes, (size_t)(cols * rows), fp);

    if (result != (size_t)(cols * rows)) {
        fputs ("Reading error", stderr);
    }

    std::cout << ((float*)outputMat.data)[200] << std::endl;
    fclose(fp);
    return outputMat;
}

void testSerializeMatbin(){
    cv::Mat a = cv::Mat::ones(/*cols*/ 10, /* rows */ 5, CV_32F) * -2;
    std::string filename = "test.matbin";
    serializeMatbin(a, filename);
    cv::Mat b = deserializeMatbin(filename);
    std::cout << "Rows: " << b.rows << " Cols: " << b.cols << " type: " << b.type()<< std::endl;
}
person Nathan B    schedule 09.08.2018

использовать двоичный файл записи:

FILE* FP = fopen("D.bin","wb");
    int sizeImg[2] = { D.cols , D.rows };
    fwrite(sizeImg, 2, sizeof(int), FP);
    fwrite(D.data, D.cols * D.rows, sizeof(float), FP);
    fclose(FP);

тогда вы можете прочитать размер чтения Matlab, а затем изменить форму (type = single)

fp=fopen(fname);
data=fread(fp,2,'int');
width = data(1); height = data(2);
B = fread(fp,Inf,type);

imageOut = reshape(B,[width,height])';

fclose(fp);
person michael scheinfeild    schedule 11.05.2017