Indexing OpenCV with an unknown type of mat

I would like to access matrix elements of an unknown type:

for(int ii = 0; ii < origCols; ii++) { colIdx.at<img.type()>(0,ii) = ii+1; // make one based index } 

The expression defining the type (inside <>) must be constant, so the code above will not work. Is there a way to do this differently than just switching different types of images?

+4
source share
2 answers

After looking at some documents, I don’t think that there is OpenCV's own way to do this without avoiding branching.

If you're just worried about cleaner code, you can try the templated approach, if you don't mind templates:

 template <typename T> void dostuff(cv::Mat& colIdx, int origCols) { for(int ii = 0; ii < origCols; ii++) { colIdx.at<T>(0,ii) = (T)(ii+1); // make one based index } } void dostuff_poly(cv::Mat& colIdx, int origCols) { switch(colIdx.type()) { case CV_8UC1: dostuff<char>(colIdx, origCols); break; case CV_32FC1: dostuff<float>(colIdx, origCols); break; case CV_64FC1: dostuff<double>(colIdx, origCols); break; // and so on default: } } 

In this example, the code is quite small, so the templates do not seem to be a bad choice and provide you with the polymorphism you need without writing a bunch of redundant code.

Perhaps some of these tutorials will give you a better idea:

OpenCV Docs: Module Tutorials

OpenCV Docs: How to Scan Images

+2
source

There is no Opencv solution built into your problem, and this is a frequent pain in this library. There are three possible solutions:

  • Always use matrices with the same depth. I think this is not what you want to hear.
  • The template of the method that calls your code according to the type of elements contained in the matrix: this will work only for single-channel matrices, since the template of the .at <method should be something cv :: Point2f for the matrices for several channels.
  • Create a smart iterator class that knows how to access matrix data based on matrix depth. Sort of:

     class PtrMat { PtrMat(cv::Mat& mat, int row) { if(mat.depth() == CV_32F) { _ptr = new PtrFloat(mat, row); } else if(mat.depth() == CV_8U) { _ptr = new PtrUchar(mat, row); } ... } Ptr* _ptr }; class Ptr { virtual void set(const float& val)=0; }; class PtrFloat: public Ptr { PtrFloat(const cv::Mat& mat, int row){ _val = mat.ptr<float>(row); } void set(const float& val) { _val = val; } float* _val; } class PtrUchar: public Ptr { PtrUchar(const cv::Mat& mat, int row){ _val = mat.ptr<uchar>(row); } void set(const float& val) { _val = val; } uchar* _val; } 

Of course, with the third solution you get a lot of duplicate code. Float casting can also slow down your hinges. In this case, the solution is not ideal.

+1
source

All Articles