web-dev-qa-db-fra.com

Comment écrire un Float Mat dans un fichier OpenCV

J'ai une matrice

Mat B(480,640,CV_32FC1);

contenant des valeurs flottantes..Je veux écrire cette matrice dans un fichier qui pourrait être ouvert dans le bloc-notes ou dans MS Word ou Excel pour voir les valeurs à l'intérieur et pour le stockage .... Fonction imwrite peut enregistrer 8 bits ou 16 image -bits seulement ..

Déposez vos suggestions si cela pouvait être fait ?? si oui comment ??

25
Karthik Murugan

Utilisation d'appels d'API OpenCV purs:

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

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

L'extension de fichier peut être xml ou yml . Dans les deux cas, vous obtenez un petit en-tête que vous pouvez facilement supprimer/analyser, vous avez alors accès aux données dans un format à virgule flottante J'ai utilisé cette approche avec succès (avec les fichiers yml) pour obtenir des données dans Matlab et Matplotlib

Pour obtenir les données:

  1. ouvrir le fichier avec n'importe quel éditeur 
  2. puis supprimez tout le texte et les chiffres sauf le contenu de la balise de données (c'est-à-dire les valeurs de pixel). 
  3. Une fois terminé, enregistrez votre fichier avec une extension txt ou csv et ouvrez-le avec matlab (glisser-déposer fonctionne).

Voilà. Vous devrez peut-être remodeler la matrice résultante dans la ligne de commande matlab si elle n'a pas deviné correctement la taille de l'image.

39
sansuiso

Vous pouvez écrire cv::Mat dans un fichier texte à l'aide d'une simple gestion de fichier C++.

Voici comment vous pouvez le faire:

#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);

}
16
sgarizvi

OpenCV peut sérialiser (enregistrer) ses objets aux formats JSON, XML ou YAML. Vous pouvez utiliser n’importe quel éditeur qui comprend ces formats pour lire ces fichiers, ou utiliser OpenCV pour télécharger des données (désérialiser) à partir de ces fichiers. Vous trouverez une explication détaillée de la procédure à suivre ici ici . En bref, pour stocker les données dans le fichier xml-, vous devez appeler

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.

Si vous souhaitez utiliser JSON ou YAML, modifiez simplement l'extension en .json ou .yaml/.yml - openCV comprendra automatiquement vos intentions.

La chose importante est la commande

fs << "cameraMatrix" << cameraM;

la chaîne "cameraMatrix" est le nom de la balise, sous lequel cette matrice sera stockée et à l'aide de laquelle cette matrice pourra être trouvée plus tard dans le fichier.

Notez que le format xml ne vous autorisera pas à utiliser des noms de balises avec des espaces et des caractères spéciaux, car seules les valeurs alphanumériques, les points, les tirets et les caractères de soulignement sont autorisés (voir XML pour plus de détails), alors que vous pouvez utiliser YAML et JSON.

fs << "Camera Matrix" << cameraM;
2
John Smith

utiliser write binary:

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);

alors vous pouvez lire dans matlabread size puis reshape (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);
2

J'ai écrit ce code:

#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;
}
0
Nadav B