多くの例/チュートリアルで、マトリックスアクセスに中括弧演算子「()」を使用していることに気づきました。これは、場合によっては混乱を招きます。
問題は次のとおりです。Mという名前の*m行列(たとえば、3x4)があるとします。「M(0)」、「M(1)」、またはその他の特異なパラメーターを介してアクセスすると、どの要素が返されますか。中かっこの中?行と列の両方を指定することになっていると思いました(「M(0,1)」など)。
多くの例/チュートリアルで、マトリックスアクセスに中括弧演算子「()」を使用していることに気づきました。これは、場合によっては混乱を招きます。
問題は次のとおりです。Mという名前の*m行列(たとえば、3x4)があるとします。「M(0)」、「M(1)」、またはその他の特異なパラメーターを介してアクセスすると、どの要素が返されますか。中かっこの中?行と列の両方を指定することになっていると思いました(「M(0,1)」など)。
線形インデックスアクセスがあります。つまり、線形の方法でメモリに直接アクセスします。
マトリックスでは、すべての要素が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())
線形インデックスを使用する前に必ず確認してください。
これはOpenCV2.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];
}