2013-07-10 42 views
7

Tóm lại, tôi muốn biết liệu có thể truy cập trực tiếp giá trị pixel của CV_32F Mat, thông qua thành viên Mat "dữ liệu uchar *" hay không.OpenCV C++: cách truy cập giá trị pixel CV_32F qua con trỏ dữ liệu uchar

tôi có thể làm điều đó với không có vấn đề nếu Mat là CV_8U, ví dụ:

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

Vấn đề là khi tôi cố gắng để làm các hoạt động cùng với các ma trận sau,

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

Cảm ơn rất nhiều, Valerio

+0

Có bất kỳ lý do nào không sử dụng 'float * p = B.data'; – William

+2

mmm không, bạn không thể làm điều này! B.data là một con trỏ đến uchar! Đây là một thành viên dữ liệu trong Mat! –

+0

oups. lấy làm tiếc. tôi vội vã bình luận. nhân tiện. bỏ phiếu cho các câu trả lời bạn thích và chấp nhận câu trả lời có hiệu quả. – William

Trả lời

5

Lưu ý rằng CV_32F có nghĩa là các phần tử là float thay vì uchar. Chữ "F" ở đây có nghĩa là "phao". Và chữ "U" trong CV_8U là viết tắt của unsigned integer. Có lẽ đó là lý do tại sao mã của bạn không cung cấp đúng giá trị. Bằng cách tuyên bố p là uchar*, p[4*B.step+5] làm cho p di chuyển đến hàng thứ năm và tạm ứng sizeof(uchar)*5, có xu hướng sai. Bạn có thể thử

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

nhưng tôi không chắc liệu nó có hoạt động hay không. Dưới đây là một số cách để vượt qua các dữ liệu của [i, j] để giá trị:

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

Cách thứ 3 không chỉ là ví dụ, vì nó dễ dàng tràn. Ngoài ra, một ma trận 6x5 nên được tạo bởi B.create(6, 5, CV_32FC1), tôi nghĩ vậy?

+0

Cảm ơn, cách thứ 3 là những gì tôi đang tìm kiếm. Tuy nhiên có điều gì đó vẫn chưa rõ ràng với tôi. Tôi đã sử dụng công thức này: –

+0

ops, sai địa điểm viết thư trả lời? –

+0

Ok, vui lòng làm rõ điểm này: ở chế độ thứ 3 bạn sử dụng số 5. ​​Bạn có muốn B.step thay vì số 5 không? Cảm ơn. –

14

Bạn có thể sử dụng ptr phương pháp mà trả về con trỏ đến ma trận liên tiếp:

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

Bạn cũng có thể đúc data con trỏ đến nổi và sử dụng elem_step thay vì step nếu ma trận là liên tục:

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

Nó hoạt động! Cảm ơn. –

+1

nó hoạt động ngay cả khi Mat không liên tục. – Kiran

Các vấn đề liên quan