OpenCV - 访问Mat矩阵中的元素

2012.06.07 补记:半年前我对 OpenCV 还不了解,OpenCV 提供多种方法访问 Mat 中的元素,十分方便。这篇文章中提及的几种方法需要重新修改。

Mat矩阵中数据指针 Mat.data 是uchar类型指针,CV_8U 系列可以通过计算指针位置快速地定位矩阵中的任意元素。

二维单通道元素可以用 Mat::at(i, j) 访问,i 是行序号,j 是列序号。

但对于多通道的非 unsigned char 类型矩阵来说,以上方法都不好

注:后来知道可以通过类型转换,用指针访问 data 数据,见后文

可以用 Mat::ptr() 来获得指向某行元素的指针,在通过行数与通道数计算相应点的指针。

参照 OpenCV 的 Mat::at() 函数,写了一个访问二维Mat矩阵的两个简单的小函数,没有边界检查。

#include <opencv2/core/core.hpp>

template<typename ItemType>
ItemType* getMatPointPtr(cv::Mat & src, int i , int j , int c = 0)
{
    ItemType* curRow = src.ptr<itemType>(i);
    return curRow + j * src.channels() + c;
}

template<typename ItemType>
ItemType getMatPoint(cv::Mat & src, int i , int j , int c = 0)
{
    ItemType* curRow = src.ptr<itemType>(i);
    return *(curRow + j * src.channels() + c);
}

OpenCV 中的 Mat::at() 代码有严格的边界检测,Mat::ptr() 也有边界检测,但代码中没有检测 j 是否越界。

以下是 2012 年 1 月 12日补写:

可以通过转换指针类型,访问非uchar类型的Mat元素。

例如图像是CV_64FC1格式,可以将Mat.data指针直接转换成double*类型:

// imgMat is a image.
double* pimg = (double*)(imgMat.data)

也可以用C++中的显式转换符static_cast,不过要通过void*类型过渡:

void* pvoid = static_cast<void*>(imgMat.data);
double* pimg = static_cast<double*>(pvoid);

这种方式在 Debug 模式下速度提升非常显著,但没有任何的边界检查和异常处理,使用时必须十分小心。 使用 Mat::ptr 的速度和直接使用这种方法差不多,多一层保护总比没有保护强。