2013-07-10 12 views
7

Krótko mówiąc, chciałbym wiedzieć, czy możliwy jest bezpośredni dostęp do wartości pikseli maty CV_32F, za pośrednictwem elementu macie "uchar * data".OpenCV C++: jak uzyskać dostęp do wartości pikseli CV_32F przez wskaźnik danych ucharowych

mogę to zrobić bez problemu, jeśli Mat to CV_8U, na przykład:

// a matrix 5 columns and 6 rows, values in [0,255], all elements initialised at 12 
cv:Mat A; 
A.create(5,6, CV_8UC1); 
A = cv::Scalar(12); 

//here I successfully access to pixel [4,5] 
uchar *p = A.data; 
int value = (uchar) p[4*A.step + 5]; 

Problem jest, gdy próbuję wykonać tę samą operację z następującą matrycą,

// a matrix 5 columns, 6 rows, values in [0.0, 1.0], all elements initialised at 1.2 
cv::Mat B; 
B.create(5,6, CV_32FC1); 
B = cv::Scalar(1.2); 

//this clearly does not work, no syntax error but erroneous value reported! 
uchar *p = B.data; 
float value = (float) p[4*B.step + 5]; 

//this works, but it is not what I want to do! 
float value = B.at<float>(4,5); 

Dzięki dużo, Valerio

+0

Czy istnieje jakikolwiek powód, aby nie używać 'float * p = B.data'; – William

+2

mmm nie, nie możesz tego zrobić! B.data jest wskaźnikiem do uchar! To jest członek danych w Mat! –

+0

oups. Przepraszam. rzuciłem się, by skomentować. tak poza tym. zagłosuj na odpowiedzi, które Ci się podobają, i zaakceptuj to, które działa. – William

Odpowiedz

5

Należy pamiętać, że CV_32F oznacza, że ​​elementy są float zamiast uchar. "F" oznacza tutaj "pływak". A "U" w CV_8U oznacza unsigned integer. Może dlatego twój kod nie daje właściwej wartości. Po zadeklarowaniu wartości p jako uchar*, p[4*B.step+5] powoduje, że p przechodzi do piątego rzędu i przesuwa się o sizeof(uchar)*5, które wydają się błędne. Możesz spróbować:

float value = (float) p[4*B.step + 5*B.elemSize()] 

, ale nie jestem pewien, czy to zadziała. Oto kilka sposobów, aby przekazać dane z [i, j] do wartości:

  1. value = B.at<float>(i, j)
  2. value = B.ptr<float>(i)[j]
  3. value = ((float*)B.data)[i*B.step+j]

The 3rd sposób nie jest jednak zalecane, ponieważ jest to łatwe przepełnić. Poza tym, matryca 6x5 powinna być tworzona przez B.create(6, 5, CV_32FC1), tak myślę?

+0

Dzięki, trzeci sposób był tym, czego szukałem. Niemniej jednak wciąż jest dla mnie niejasna kwestia. Użyłem tej formuły: –

+0

ops, złe miejsce, w którym pisać odpowiedź? –

+0

Ok, proszę wyjaśnić ten punkt: w trzecim trybie używasz numeru 5. Czy powinien to być B.step zamiast numeru 5? Dzięki. –

14

Można użyć ptr metodę, która zwraca wskaźnik do wiersza macierzy:

for (int y = 0; y < mat.rows; ++y) 
{ 
    float* row_ptr = mat.ptr<float>(y); 
    for (int x = 0; x < mat.cols; ++x) 
    { 
     float val = row_ptr[x]; 
    } 
} 

Można też rzucić data wskaźnik do pływaka i używać elem_step zamiast step jeśli macierz jest ciągła:

float* ptr = (float*) mat.data; 
size_t elem_step = mat.step/sizeof(float); 
float val = ptr[i * elem_step + j]; 
+0

To działa! Dzięki. –

+1

działa nawet wtedy, gdy Mat nie jest ciągły. – Kiran

Powiązane problemy