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

Posted

技术标签:

【中文标题】通过未知类型的 Mat 进行 OpenCV 索引【英文标题】:OpenCV indexing through Mat of unknown type 【发布时间】:2012-07-16 20:03:28 【问题描述】:

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

for(int ii = 0; ii < origCols; ii++)

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

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

【问题讨论】:

【参考方案1】:

在浏览了一些文档之后,我认为没有一种原生 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 docs: core module tutorials

OpenCV docs: How to scan images

【讨论】:

【参考方案2】:

对于您的问题,没有原生的 Opencv 解决方案,而且这个库经常让您感到痛苦。有三种可能的解决方案:

    始终使用具有相同深度的矩阵。我想这不是你想听到的。 通过矩阵中包含的元素的类型来模板调用代码的方法:这仅适用于单通道矩阵,因为 .at 方法的模板必须是 cv::Point2f用于多个通道的矩阵。

    创建一个“智能”迭代器类,它将知道如何根据矩阵深度访问矩阵数据。比如:

    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 下面的回答对于我想做的事情来说更清晰,但是你提出了几个好点。感谢您的回复。这种组合帮助我确定了我将尝试什么,这可能是基于模板的。

以上是关于通过未知类型的 Mat 进行 OpenCV 索引的主要内容,如果未能解决你的问题,请参考以下文章

对整个 Mat 图像进行排序并在 OpenCV 中存储索引?

opencv编程中cvMat到Mat如何进行数据转换?

如何通过另一个具有位置(索引)的垫子访问opencv中的矩阵数据

OpenCV:Mat,IplImage,CvMat类型转换

OpenCV inRange 更改 Mat 类型

opencv中Mat与IplImage,CVMat类型之间转换