2013-07-10 5 views
7

Kurz möchte ich wissen, ob es möglich ist, Pixel-Wert einer CV_32F Mat direkt durch Mat Mitglied "Uchar * Daten" zugreifen.OpenCV C++: wie Zugriff Pixelwert CV_32F durch UCHAR-Datenzeiger

ich kann es ohne Probleme, wenn Mat CV_8U ist, zum Beispiel:

// 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]; 

Das Problem ist, wenn ich versuche, den gleichen Vorgang mit der folgenden Matrix zu tun,

// 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); 

Dank viel, Valerio

+0

gibt es irgendein Grund, nicht 'float * p = B.data' zu verwenden; – William

+2

mmm nein, das geht nicht! B.data ist ein Zeiger auf uchar! Dies ist ein Datenelement in Mat! –

+0

Ausgänge. Es tut uns leid. Ich beeilte mich zu kommentieren. Apropos. Stimme die Antworten ab, die du magst und akzeptiere die, die funktioniert. – William

Antwort

5

Beachten Sie, dass CV_32F bedeutet, dass die Elemente float anstelle von uchar sind. Das "F" bedeutet hier "float". Und das "U" in CV_8U steht für unsigned integer. Vielleicht gibt dein Code deshalb nicht den richtigen Wert. Durch Deklarieren von p als uchar*, p[4*B.step+5] wird p in die fünfte Zeile verschoben und sizeof(uchar)*5 vorgerückt, was tendenziell falsch ist. Sie können versuchen

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

aber ich bin mir nicht sicher, ob es funktioniert. Hier sind einige Möglichkeiten, um die Daten von [i, j], um Wert zu übergeben:

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

Die 3. Art und Weise allerdings nicht zu empfehlen, da es einfach ist, Überlaufen. Außerdem sollte eine 6x5-Matrix von B.create(6, 5, CV_32FC1) erstellt werden, denke ich?

+0

Danke, der 3. Weg war, was ich gesucht habe. Trotzdem ist mir noch etwas unklar. Ich habe diese Formel verwendet: –

+0

Ops, falscher Ort, wo Antwort schreiben? –

+0

Ok, bitte verdeutliche diesen Punkt: Im 3. Modus benutzt du Nummer 5. Soll es B.step statt Nummer 5 sein? Vielen Dank. –

14

Sie ptr Methode, die Zeiger auf Matrix Zeile zurückgibt verwenden können:

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

Sie auch data Zeiger werfen können und elem_step schweben anstelle von step wenn Matrix Dauer ist:

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

Es funktioniert! Vielen Dank. –

+1

es funktioniert, auch wenn Mat nicht kontinuierlich ist. – Kiran