6

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

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

定义类型的表达式(在 <> 内)必须是一个常量,所以上面的代码不起作用。除了切换不同的图像类型之外,还有其他方法吗?

4

2 回答 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 文档:如何扫描图像

于 2012-07-16T22:14:25.530 回答
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;
    }
    

当然,使用第三种解决方案,您最终会得到大量重复的代码。浮动铸造也可以减慢你的循环。在这种情况下,没有任何解决方案是完美的。

于 2012-07-17T14:18:36.767 回答