OpenCV通过未知类型的Mat进行索引

7

我想访问一个未知类型的矩阵元素:

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

表达式定义的类型(在<>中)必须是常量,因此上述代码无法工作。除了在不同的图像类型之间切换之外,还有其他的方法可以做到这一点吗?
2个回答

4

在查看了一些文档后,我认为没有本地OpenCV方法可以避免分支。

如果您只关心更清晰的代码,可以尝试模板方法,只要您不介意使用模板:

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:
    }
}

在这个例子中,代码相对较小,因此模板似乎是一个不错的选择,并且可以为您提供多态性而不需要编写大量冗余代码。
也许其中一些教程会给您更好的想法: OpenCV文档:核心模块教程 OpenCV文档:如何扫描图像

1

对于您的问题,Opencv 没有本地解决方案,这是该库经常出现的痛点。有三种可能的解决方案:

  1. 始终使用相同深度的矩阵。我猜这不是你想听到的。
  2. 通过矩阵中包含的元素类型对调用代码的方法进行模板化:这仅适用于单通道矩阵,因为.at<>方法的模板必须是cv::Point2f之类的东西,以适用于多通道矩阵。
  3. 创建一个“智能”迭代器类,它将根据矩阵深度知道如何访问矩阵数据。例如:

    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;
    }
    
当然,第三个解决方案会导致大量重复的代码。浮点数转换也可能会减慢循环速度。在这种情况下,没有完美的解决方案。

我认为Toti在下面的回答更适合我想要做的事情,但你也提出了几个好点子。感谢您的回复。这种组合帮助我找到了我将尝试的方法,可能会基于模板。 - zzzz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接