web-dev-qa-db-ja.com

OpenCV C ++の「Mat」オブジェクト(CvMatオブジェクトではない)のマトリックス要素へのアクセス

OpenCV 2.0の新しい「Mat」クラスの行、列で要素にアクセスする方法は?ドキュメントは以下にリンクされていますが、私はそれを理解することができませんでした。 http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat

30
neptune

ドキュメントについて:

http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat

それは言います:

(...)行列要素タイプがわかっている場合、例えばフロートである場合、at <>()メソッドを使用できます

つまり、次を使用できます。

_Mat M(100, 100, CV_64F);
cout << M.at<double>(0,0);
_

_Mat__クラスを使用する方が簡単かもしれません。 Matのテンプレートラッパーです。 _Mat__には、要素にアクセスするためにoperator()がオーバーロードされています。

49
J. Calleja

上記のアイデアは素晴らしいものです。高速アクセス(リアルタイムアプリケーションを作成する場合)の場合は、次のことを試すことができます。

//suppose you read an image from a file that is gray scale
Mat image = imread("Your path", CV_8UC1);
//...do some processing
uint8_t *myData = image.data;
int width = image.cols;
int height = image.rows;
int _stride = image.step;//in case cols != strides
for(int i = 0; i < height; i++)
{
    for(int j = 0; j < width; j++)
    {
        uint8_t val = myData[ i * _stride + j];
        //do whatever you want with your value
    }
}

ポインターアクセスは、Mat.at <>アクセスよりもはるかに高速です。それが役に立てば幸い!

10

@Jに基づいてカレハは、あなたには2つの選択肢があると言いました

方法1-ランダ​​ムアクセス

Matの要素にランダムにアクセスする場合は、単に使用します

Mat.at<data_Type>(row_num, col_num) = value;

方法2-連続アクセス

継続的なアクセスが必要な場合、OpenCVはSTL iteratorおよびそれ以上のC++ スタイル

MatIterator_<double> it, end;
for( it = I.begin<double>(), end = I.end<double>(); it != end; ++it)
{
    //do something here
}

または

for(int row = 0; row < mat.rows; ++row) {
    float* p = mat.ptr(row); //pointer p points to the first place of each row
    for(int col = 0; col < mat.cols; ++col) {
         *p++;  // operation here
    }
}

方法2がどのように機能するかを理解するのが難しい場合は、記事 Cの動的な2次元配列 のブログ投稿から写真を借ります。

下の写真をご覧ください。

enter image description here

4
WY Hsu

OCVは、要素の種類を知らずにこれを実行できないことを確認するために邪魔になりませんが、簡単にコード化できるが、あまり効率的ではなく、型に依存せずに読み取る方法が必要な場合は、次のようなものを使用できます

double val=mean(someMat(Rect(x,y,1,1)))[channel];

それをうまく行うには、タイプを知る必要があります。 at <>メソッドは安全な方法ですが、データポインターへの直接アクセスは、正しく行うと一般的に高速です。

1
Ben