OpenCV indexing through Mat of unknown type

后端 未结 2 576
失恋的感觉
失恋的感觉 2021-01-03 00:34

I would like to access the elements of a matrix of unknown type:

for(int ii = 0; ii < origCols; ii++)
{
  colIdx.at(0,ii) = ii+1; // mak         


        
相关标签:
2条回答
  • 2021-01-03 01:17

    After looking through some of the docs, I don't think there is a native OpenCV way to do it without avoiding branching.

    If you are just concerned about cleaner code, you could try a template approach so long as 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 rather small, so templates seems like it wouldn't be a bad choice and would give you the polymorphism you want without writing a bunch of redundant code.

    Maybe some of these tutorials would give you a better idea:

    OpenCV docs: core module tutorials

    OpenCV docs: How to scan images

    0 讨论(0)
  • 2021-01-03 01:18

    There is no native Opencv solution to your problem, and it is a frequent pain with this library. There are three possible solutions:

    1. Always use matrices with the same depth. I guess that's not what you want to hear.
    2. Template the method that calls your code by the type of the elements contained in the matrix: this will only work for single channel matrices, as the template of the .at<> method will have to be something by cv::Point2f for matrices for multiple channels.
    3. Create a "smart" iterator class that will know how to access matrix data based on the matrix depth. Something like:

      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 end up with lots of duplicated code. Float casting can also slow down your loops. No solution is perfect in this case.

    0 讨论(0)
提交回复
热议问题