0

I created a 3D float matrix in opencv, c++ by the help of brunocodutra in his answer. My matrix is 1024*1024*N (N is not a constant number, it might change)

When I say const int N = some_number; I can say

typedef Vec<float,N> VecNf;

After this type definition, I can play with the matrix. However, I don't want N to be constant, thus I'm stuck there. I believe, there should be some easy solution for this but I couldn't find any yet.

EDIT: I added code for saving a Matrix. Assume I properly created 3D Mat noise having 100 channels.

typedef Vec<float,100> Vec100f;
void writeNoise_ND(string filename,Mat noise) throw(){
    int chans = noise.channels();
    int sz = noise.rows;

    FILE* fp = fopen(filename.c_str(),"wb");
    if (!fp){
        perror("out directory is not found\n");
    }
    float *buffer = new float[sz];

    for(int c = 0; c < chans; c++){
        for(int i=0;i<sz;++i){
            for(int j=0;j<sz;++j)
                buffer[j]=noise.at<Vec100f>(i,j)[c];
            fwrite(buffer,sizeof(Vec100f),sz,fp);
        }
    }

    fclose(fp);
    free(buffer);   
}

Could somebody direct me? If it is already asked question, sorry about it.

Thanks in advance,

Community
  • 1
  • 1
smttsp
  • 4,011
  • 3
  • 33
  • 62
  • 1
    Could you elaborate on the "Saving" part ? I think you mean declaring. – Félix Cantournet Sep 08 '14 at 13:39
  • I deleted my answer as it is obviously not what you want. Your problem stems from the fact that `Vec` is of size N that is compile-time constant. The way I see it you can change your Type so that Mat::at return `std::vector` instead of `Vec`. `std::vector` can be of a size not known at compile-time. Another approach would be to write a wrapper to serialize and deserialize your Mat. Such a function could reshape the Mat before writing the data and the size of each dimension + number of channels. You would need a reciproque function to read it back. – Félix Cantournet Sep 08 '14 at 14:45
  • I didnt get wrapper part. Could you elaborate it? Is it like having `vector` instead of `N dimensional Mat`? – smttsp Sep 08 '14 at 16:52

1 Answers1

0

Your Mat seems to be what I think of as a 2D Mat with N channels. just as a typical image is a 2D Mat 3 channels (RGB). THe following code will store all of channels 0, followed by all of channel 1 etc, up to channel N-1:

#include <fstream>
#include <vector>

void writeNoise(string filename, Mat noise)
{
    int chans = noise.channels();
    int sz = noise.rows;  // should check that noise.cols is == noise.rows

    std::ofstream f(filename, ios::out | ios::binary);

    if (!f.is_open())
        throw std::ofstream::failure("out directory is not found\n");

    std::vector<float> buffer(sz);

    for(int c = 0; c < chans; c++)
    {
        for(int i = 0; i < sz; ++i)
        {
            float* p = noise.ptr<float>(i) + c;

            for(int j = 0; j < sz; ++j)
            {
                buffer[j] = *p;
                p += chans;
            }
            f.write((const char *) &buffer[0], sizeof(float) * buffer.size());
        }
    }

    f.close();
}

if you want to access channel 15 at (row = 15, col = 15), given that you don't know the number of channels at compile time (so you can't use at()), you can do this;

float get(cv::Mat m, int row, int col, int chan)
{
    float* p = m.ptr<float>(row);
    return p[col * m.channels() + chan];    
}

/* ... */

cout << get(noise, 15, 15, 15) << endl;

Note that it would be inappropriate to use a get() like that for sequential access to pixels (because it would be very slow compared to accessing the pixels like I did in writeNoise())

Bull
  • 11,771
  • 9
  • 42
  • 53
  • This looks to be nice, but why there is `(char *)` in `f.write((char *) &buffer[0], sizeof(float) * buffer.size());`? Also, accessing an element is still a problem? For example, I want to print out `noise[15,15,15]th element`, how will I access that element? – smttsp Sep 08 '14 at 16:16
  • `write()` takes a `const char *` argument and `&buffer[0]` is a `float*` so explicit cast is required - I corrected my answer by adding `const`. As for accessing an element, that wasn't part of your question, but I have added one possible way to my answer. – Bull Sep 08 '14 at 23:57