Ask Your Question
0

read formated matrix from text file

asked 2019-01-26 15:21:15 -0500

js4267 gravatar image

updated 2019-01-26 15:24:17 -0500

Hello

I know OpenCV allow to format matrix using different representation of the data thanks to the function: format e.g.:

std::cout<<cv::format(my_matrix, cv::Formatter::FMT_NUMPY)<<std::endl;

I would like to know if there is an already existing function that can read the formatted data from a text file.

Thanks in advance.

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2019-01-27 01:32:37 -0500

berak gravatar image

unfortunately, this is one way (write) only, there is no builtin way to read it back.

you can use cv::FileStorage to serialize your data, but if you were looking for an easy way to interchange data between opencv / numpy -- not so ;(

edit flag offensive delete link more

Comments

1

well if i rember right - in python its easy to serialize / read numpy arrays.You have this functionality because of numpy library.

holger gravatar imageholger ( 2019-01-27 07:22:39 -0500 )edit

if that was the problem, yes. there's also a hidden function in the dnn module, to read .npz

berak gravatar imageberak ( 2019-01-27 07:24:39 -0500 )edit
2

Ok thank you very much to both of you :). I actually did a piece of code that can "interpret" the output of the example I give in order to create and fill a matrix from it, I'll give the code later as an update of this post.

js4267 gravatar imagejs4267 ( 2019-01-27 10:22:38 -0500 )edit

@berak I made a mistake. Could you please reopen the question and mark it as solve. Sincerely Sorry.

js4267 gravatar imagejs4267 ( 2019-01-27 10:23:52 -0500 )edit

@js4267, sure, no problem ;) (and we're all humans...)

also, -- really, if you have a working solution, you should post an answer !

(that'll be helpful to a lot of other folks !)

berak gravatar imageberak ( 2019-01-27 10:29:35 -0500 )edit
1

answered 2019-01-28 14:47:05 -0500

js4267 gravatar image

Hello

Here is the code I made in order to read one or more matrices written in a text file. It is all but the most efficient way to do it and it is limitted to the numpy formating.

utils.h

#include <opencv2/core.hpp>
#include <fstream>

namespace utils
{
class StdFileStreamFormater
{
public:

    inline StdFileStreamFormater(std::fstream& _stream):
        stream(_stream)
    {}

    StdFileStreamFormater(const StdFileStreamFormater&) = delete;
    StdFileStreamFormater(StdFileStreamFormater&&) = delete;

    ~StdFileStreamFormater() = default;

    StdFileStreamFormater& operator=(const StdFileStreamFormater&) = delete;
    StdFileStreamFormater& operator=(StdFileStreamFormater&&) = delete;


    void writeMatrixWithNumpyFmt(cv::InputArray _tmp);

    void readFileWithNumpyFmt(cv::OutputArray _out);



    inline std::fstream& getStream()const { return this->stream; }

    inline operator std::fstream&()const { return this->stream; }

private:

    std::fstream& stream;
};
} //utils

utils.cpp

#include <fstream>
#include <sstream>
#include <iterator>
#include <numeric>

namespace utils
{

void StdFileStreamFormater::writeMatrixWithNumpyFmt(cv::InputArray _tmp)
{

    CV_Assert(_tmp.isMat() || _tmp.isUMat() || _tmp.isGpuMat() || _tmp.isMatVector() || _tmp.isUMatVector() || _tmp.isGpuMatVector() || (_tmp.kind() == cv::_InputArray::EXPR));

    if(!_tmp.isVector())
    {
        if(!_tmp.isGpuMat())
            this->stream<<cv::format(_tmp.getMat(), cv::Formatter::FMT_NUMPY)<<std::endl;
        else
        {
           cv::Mat tmp(_tmp.getGpuMat());
           this->stream<<cv::format(tmp, cv::Formatter::FMT_NUMPY)<<std::endl;
        }
    }
    else
    {
        std::vector<cv::Mat> tmp;

        if(!_tmp.isGpuMatVector())
            _tmp.getMatVector(tmp);
        else
        {
            std::vector<cv::cuda::GpuMat> tmp2;

            _tmp.getGpuMatVector(tmp2);

            tmp.resize(tmp2.size());

            std::transform(tmp2.begin(), tmp2.end(), tmp.begin(),[](const cv::cuda::GpuMat& src)->cv::Mat{ return cv::Mat(src); });
        }

        for(const cv::Mat& image : tmp)
            this->stream<<cv::format(image, cv::Formatter::FMT_NUMPY)<<std::endl;
    }
}

void StdFileStreamFormater::readFileWithNumpyFmt(cv::OutputArray _out)
{

    static std::unordered_map<cv::String, int> Strings2Types =
    {
        std::make_pair("uint8",CV_8U),
        std::make_pair("int8",CV_8S),
        std::make_pair("uint16",CV_16U),
        std::make_pair("int16",CV_16S),
        std::make_pair("int32",CV_32S),
        std::make_pair("float32",CV_32F),
        std::make_pair("foat64",CV_64F),
    };

    // Step 0-a): Copy the content of the file in memory.
    std::ostringstream oss;

    oss<<this->stream.rdbuf();

    cv::String buffer = oss.str();

    // Step 0-b): Count the number of matrices in the file.
    int nb_images = 0;

    size_t init = buffer.find("array");

    while(init != cv::String::npos)
    {
        nb_images++;

        init = buffer.find("array",init + 5);
    }

    std::vector<cv::Mat> images;

    images.resize(nb_images);


    init = 0;

    // For each matrix... (there is prior that each matrix represent an image. This prior may be wrong.)
    for(int i=0;i<nb_images;i++)
    {

        // Step 0-c): Copy the data of the current matrix to a local buffer.

        init = buffer.find("array", init);


       // Step 1): From the buffer get the depth of the current matrix.
        cv::Range matrix_position;

        matrix_position.start = static_cast<int>(init)+7;
        matrix_position.end = buffer.find("dtype", static_cast<size_t>(matrix_position.start));

        cv::String strType;

        size_t j = static_cast<size_t>(matrix_position.end + 7);

        if(buffer[j] == '\'')
            j++;

        while(buffer[j]!='\'')
            strType.push_back(buffer[j++]);

        int depth = Strings2Types[strType];

        cv::String data = buffer.substr(static_cast<size_t>(matrix_position.start), static_cast<size_t>(matrix_position.size()) );

       // Step 2): From the duplication of the data for the current matrix count the number of channels.
        int cns = 1;

        init = data.find("[[[");

        if(init != cv::String::npos)
        {
            size_t end = data.find("]",init+3);

            init = data.find(",",init+3);

            while(init != cv::String::npos)
            {
                cns++;

                init = data.find(",",init+1);

                if(init>end)
                    break;
            }
        }

       // Step 3): From the duplication of the data for the current matrix count the number of ...
(more)
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2019-01-26 15:21:15 -0500

Seen: 31 times

Last updated: Jan 28