我在许多示例/教程中注意到人们使用大括号运算符“()”进行矩阵访问,这在某些情况下让我感到困惑。
问题是:假设我们有一个名为 M 的 *m 矩阵(例如 3x4)。通过“M(0)”或“M(1)”或任何其他单数参数访问它会返回哪些元素大括号里面?我认为您应该同时指定行和列(如“M(0,1)”或类似的东西)。
我在许多示例/教程中注意到人们使用大括号运算符“()”进行矩阵访问,这在某些情况下让我感到困惑。
问题是:假设我们有一个名为 M 的 *m 矩阵(例如 3x4)。通过“M(0)”或“M(1)”或任何其他单数参数访问它会返回哪些元素大括号里面?我认为您应该同时指定行和列(如“M(0,1)”或类似的东西)。
你看到的是线性索引访问——即以线性方式直接访问内存。
在矩阵中,所有元素都存储在一大块内存中,每一行都在前一行之后。这就是为什么,如果你想在(i, j)
你写的位置访问一个元素,比如
elem = matrix(j + rowWidth*i)
但你可以简单地访问它
elem = matrix(k)
当您不关心行/列位置时,这很有用,例如当您总结矩阵中的所有元素时:
count = width*height;
sum=0;
for(i=0;i<count;i++)
sum+=matrix(i);
或者当您预先计算线性索引时。
请注意,如果矩阵碰巧没有存储在连续的内存块中(例如更大矩阵中的感兴趣区域),这种技术可能会产生一些最疯狂的错误。if (myMat.isContinuous())
在使用线性索引之前务必检查!
这是来自 OpenCV 2.4.2
template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1)
{
return ((_Tp*)(data + step.p[0]*i0))[i1];
}
template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0)
{
return this->at<_Tp>(i0);
}
template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2)
{
return this->at<_Tp>(i0, i1, i2);
}
Mat::at(int i0)
这是Mat_
公开继承自的定义Mat
template<typename _Tp> inline const _Tp& Mat::at(int i0) const
{
if( isContinuous() || size.p[0] == 1 )
return ((const _Tp*)data)[i0];
if( size.p[1] == 1 )
return *(const _Tp*)(data + step.p[0]*i0);
int i = i0/cols, j = i0 - i*cols;
return ((const _Tp*)(data + step.p[0]*i))[j];
}