web-dev-qa-db-fra.com

Accéder à un élément de matrice dans l'objet "Mat" (pas l'objet CvMat) dans OpenCV C ++

Comment accéder aux éléments par ligne, col dans la nouvelle classe "Mat" d'OpenCV 2.0? La documentation est liée ci-dessous, mais je n'ai pas pu la comprendre. http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat

30
neptune

Sur la documentation:

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

Ça dit:

(...) si vous connaissez le type d'élément de matrice, par ex. c'est float, alors vous pouvez utiliser la méthode at <> ()

Autrement dit, vous pouvez utiliser:

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

Il est peut-être plus facile d'utiliser la classe Mat_. Il s'agit d'un wrapper de modèle pour Mat. Mat_ A la operator() surchargée pour accéder aux éléments.

49
J. Calleja

Les idées fournies ci-dessus sont bonnes. Pour un accès rapide (au cas où vous souhaiteriez faire une application en temps réel), vous pouvez essayer ce qui suit:

//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
    }
}

L'accès au pointeur est beaucoup plus rapide que l'accès Mat.at <>. J'espère que ça aide!

10
Mircea Paul Muresan

Basé sur ce que @J. Calleja a dit, vous avez deux choix

Méthode 1 - Accès aléatoire

Si vous souhaitez accéder de manière aléatoire à l'élément de Mat, utilisez simplement

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

Méthode 2 - Accès continu

Si vous souhaitez un accès continu, OpenCV fournit un itérateur Mat compatible avec STL iterator et c'est plus C++ style

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

ou

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
    }
}

Si vous avez du mal à comprendre comment fonctionne la méthode 2, j'emprunte l'image à un article de blog dans l'article Dynamic Two-dimensioned Arrays in C , ce qui est beaucoup plus intuitif et compréhensible.

Voir l'image ci-dessous.

enter image description here

4
WY Hsu

OCV fait tout son possible pour vous assurer que vous ne pouvez pas le faire sans connaître le type d'élément, mais si vous voulez un moyen facilement codable mais pas très efficace de le lire de manière agnostique, vous pouvez utiliser quelque chose comme

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

Pour bien le faire, vous devez cependant connaître le type. La méthode at <> est le moyen sûr, mais l'accès direct au pointeur de données est généralement plus rapide si vous le faites correctement.

1
Ben