2011-12-14 34 views
6

Tôi sử dụng OpenCV để hủy đặt lại các điểm sau khi hiệu chỉnh máy ảnh. Mã sau.Làm cách nào để hủy các điểm trong tọa độ ảnh của camera và có được tọa độ ảnh chưa phân loại tương ứng?

const int npoints = 2; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file. 
float input_points[npoints][2] = {{0,0}, {2560, 1920}}; 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2); 
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2); 

// fill src matrix 
float * src_ptr = (float*)src->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    for (int ci = 0; ci < 2; ++ci) { 
     *(src_ptr + pi * 2 + ci) = input_points[pi][ci]; 
    } 
} 

cvUndistortPoints(src, dst, &camera1, &distCoeffs1); 

Sau khi mã trên dst chứa số sau:

-8.82689655e-001 -7.05507338e-001 4.16228324e-001 3.04863811e-001 

đó là quá nhỏ so với con số trong src.

Cùng lúc đó nếu tôi undistort hình ảnh qua cuộc gọi:

cvUndistort2(srcImage, dstImage, &camera1, &dist_coeffs1); 

tôi nhận được hình ảnh nguyên bản tốt có nghĩa là tọa độ điểm ảnh không được sửa đổi để mạnh so với điểm riêng biệt.

Làm cách nào để có được sự phân biệt tương tự cho các điểm cụ thể như đối với hình ảnh? Cảm ơn.

+0

bạn có chắc camera1 và camera giống nhau không? – Sam

+0

có, giống nhau - Tôi có câu hỏi cố định. Cảm ơn bạn đã chỉ ra. Hơn nữa ban đầu tôi nhận được hành vi như vậy trong EmguCV và sau đó cố gắng tìm ra nơi hành vi như vậy được giới thiệu: trong OpenCV hoặc EmguCV chính nó. Nó xuất hiện trong OpenCV. – sergtk

Trả lời

10

Các điểm cần được "không chuẩn hóa" bằng ma trận máy ảnh.

Cụ thể hơn, sau khi tiếng gọi của cvUndistortPoints chuyển đổi sau đây cần được cũng nói thêm:

double fx = CV_MAT_ELEM(camera1, double, 0, 0); 
double fy = CV_MAT_ELEM(camera1, double, 1, 1); 
double cx = CV_MAT_ELEM(camera1, double, 0, 2); 
double cy = CV_MAT_ELEM(camera1, double, 1, 2); 

float * dst_ptr = (float*)dst->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    float& px = *(dst_ptr + pi * 2); 
    float& py = *(dst_ptr + pi * 2 + 1); 
    // perform transformation. 
    // In fact this is equivalent to multiplication to camera matrix 
    px = px * fx + cx; 
    py = py * fy + cy; 
} 

Thông tin thêm về ma trận camera tại OpenCV 'Camera Calibration and 3D Reconstruction'

UPDATE:

Tiếp theo C++ chức năng cuộc gọi nên cũng hoạt động:

std::vector<cv::Point2f> inputDistortedPoints = ... 
std::vector<cv::Point2f> outputUndistortedPoints; 
cv::Mat cameraMatrix = ... 
cv::Mat distCoeffs = ... 

cv::undistortPoints(inputDistortedPoints, outputUndistortedPoints, cameraMatrix, distCoeffs, cv::noArray(), cameraMatrix); 
1

Nó có thể là kích thước ma trận của bạn :)

OpenCV mong đợi một vectơ điểm - một cột hoặc ma trận hàng có hai kênh. Nhưng bởi vì ma trận đầu vào của bạn chỉ là 2 điểm, và số lượng kênh cũng là 1, nó không thể tìm ra đầu vào, hàng hoặc cột.

Vì vậy, điền vào một mat đầu vào còn có giá trị không có thật, và giữ chỉ là người đầu tiên:

const int npoints = 4; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file. 
float input_points[npoints][4] = {{0,0}, {2560, 1920}}; // the rest will be set to 0 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2); 
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2); 

// fill src matrix 
float * src_ptr = (float*)src->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    for (int ci = 0; ci < 2; ++ci) { 
     *(src_ptr + pi * 2 + ci) = input_points[pi][ci]; 
    } 
} 

cvUndistortPoints(src, dst, &camera1, &distCoeffs1); 

EDIT

Trong khi OpenCV định undistortPoints chấp nhận đầu vào chỉ có 2 kênh, trên thực tế, nó chấp nhận

  • 1 cột, 2 kênh, thảm nhiều hàng hoặc (và trường hợp này không được ghi)
  • 2 cột, đa liên tiếp, 1 kênh mat hoặc
  • nhiều cột, 1 hàng, 2 kênh mat

(như đã thấy trong undistort.cpp, dòng 390)

Nhưng một lỗi bên trong (hoặc thiếu thông tin có sẵn), làm cho nó sai trộn thứ hai với thứ ba, khi số cột là 2. Vì vậy, dữ liệu của bạn được coi là một 2 cột, 2 hàng, 1-kênh.

+0

Bạn có ý gì khi nói 1 kênh? Tôi sử dụng CV_32FC2 liên tục trong cvCreateMat, có nghĩa là 2 kênh. Cảm ơn. – sergtk

+1

Tôi đã xem mã nguồn của undistortPoints() func và tài liệu sai. Hãy xem phần chỉnh sửa ở trên để biết chi tiết, vui lòng – Sam

+0

Nhưng có vẻ như câu trả lời của bạn là đúng – Sam

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