smttsp
smttsp

Reputation: 4191

how to write a method for different Matrix types without explicitly specifying type of Mat in opencv c++

My question might be sitting somewhere in Stackoverflow that I couldn't find, if so, could you give me link.

Basically, I want to write a method that can be used for all matrix types. My method is as follows:

Mat my_func(Mat in){
    Mat out(in.rows, in.cols, in.type());
    for(int i =0; i < x; i++)
        for(int j =0; j < x; j++)
            out.at<in.type()>(i,j) = in.at<in.type()>(j,i); //this is just an example,
                                                 //consider that I need to use
                                                 //out.at<in.type()>(i,j) part
}

out.at<in.type()>(i,j) gives error as it doesn't accept <in.type>, it requires <double>, <float> etc.

I solved this problem by

if(in.type() == 5)
    out.at<float>(i,j) = //do something for float
else if (in.type() == 6)
    out.at<double>(i,j) = //do something for double

There should be a better way, but I couldn't find. I searched related to typedef but I couldn't understand much from what I have found.

Note that: in.type() = 5 indicates that Matrix named in is a mat of floats, similarly 6 is mat of doubles.

Thanks in advance,

Upvotes: 1

Views: 237

Answers (3)

user41986
user41986

Reputation: 81

I wrote a function to write any type of mat to txtfile which can be read in matlab using matlab function 'dlmread'

int main()
{ 
  Mat matDilate;
  SaveToNotepad(matDilate,"C://matDilate.txt");
  return 0;
}


template <class T>
void CFindObjectByThreshColorImage::PrintMat(T* image, int rows, int cols, std::string fileName)
{
try
{
    ofstream fout(fileName); 
    if(fout.is_open())
    {
        for ( unsigned int i = 0; i < rows; i ++)
        {
            for (unsigned int j = 0; j < cols; j ++)
            {
                fout << image[i*cols+j]<<"\t"; // behaves like cout - cout is also a stream
                //cerr<< image[i*cols+j]<<"\t";
            }
            fout << endl;

        }
        fout.close();
    }
}
catch (exception& e)
{
    LOG( ALG_LOGGER, Error, "CFindHoughCircle::file write Exception " + string(e.what()));
}
}

///////////////////////////////////////////////////////
>// SaveToNotepad 
>//writes the mat to the destination  fileName
>// Example :SaveToNotepad(diff_im,"C://diff_im.txt");
>//////////////////////////////////////////////////////
void CFindObjectByThreshColorImage::SaveToNotepad( Mat WriteMatrix, std::string fileName)
{        
int iImgType = WriteMatrix.type();// finding which datat type it is 

switch (iImgType)
{
case 0:
    // "CV_8U";
    PrintMat((uchar*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);// 
    break;
case 1:
    // "CV_8S";
    PrintMat(( char*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
case 2:
    //"CV_16U";
    PrintMat(( ushort*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
case 3:
    // "CV_16S";
    PrintMat(( short*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
case 4:
    // "CV_32S";
    PrintMat(( int*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
case 5:
    // "CV_32F";
    PrintMat(( float*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
case 6:
    // "CV_64F";
    PrintMat(( double*) WriteMatrix.data, WriteMatrix.rows , WriteMatrix.cols, fileName);
    break;
default:
    LOG( ALG_LOGGER, Error, "CFindHoughCircle:: Mat type Exception " + fileName);
    break;
}

Upvotes: 0

berak
berak

Reputation: 39816

m.at<type>(i,j) is a template expression. the compiler has to resolve the type at compile time.

so, any try to cheat at runtime like m1.at<m2.type()>(i,j) is doomed.

the good news is , that there are template Mat's as well, like Mat_<float> which you can access just like m(i,j) ( without the pesky template brackets ).

so, your example code might even look like:

template<class T>
Mat_<T> my_func(Mat_<T> in){
    Mat_<T> out(in.cols, in.rows);
    for(int i =0; i < in.cols; i++)
        for(int j =0; j < in.rows; j++)
            out(j,i) = in(i,j); 
    return out;
}

int main()
{
// called like :
Mat_<int> in;
Mat_<int> res = my_func(in);
return 0;
}

honestly, it's a very rare case, that you don't know your Mat's type at compile time, for those you'll still need code like if type==5 do_something, arrays of function pointers indexed by typeid or similar.

Upvotes: 4

n. m. could be an AI
n. m. could be an AI

Reputation: 120229

Better ways that come to mind:

  1. Use Mat_<...> instead of Mat.
  2. Instead of at and assignment, extract a 1×1 rectangle an use Mat::copyTo().
  3. Encapsulate assignment to a function of your own, do the case (Mat.type()) {...} routine inside that function.

Upvotes: 1

Related Questions