2013-06-09 31 views
5

Tôi đang làm việc với tập dữ liệu đã cho bằng cách sử dụng OpenCV, không có bất kỳ Kinect nào bên cạnh tôi. Và tôi muốn ánh xạ dữ liệu độ sâu nhất định cho đối tượng RGB của nó (để tôi có thể nhận được màu sắc thực tế và độ sâu)Làm cách nào để ánh xạ dữ liệu độ sâu của Kinect với màu RGB?

Vì tôi đang sử dụng OpenCV và C++, và không sở hữu Kinect, thật đáng buồn là tôi không thể sử dụng phương thức MapDepthFrameToColorFrame từ API Kinect chính thức.

Từ intrinsics camera cho và hệ số méo, tôi có thể lập bản đồ độ sâu với thế giới tọa độ, và trở lại RGB dựa trên các thuật toán cung cấp here

Vec3f depthToW(int x, int y, float depth){ 
    Vec3f result; 
    result[0] = (float) (x - depthCX) * depth/depthFX; 
    result[1] = (float) (y - depthCY) * depth/depthFY; 
    result[2] = (float) depth; 
    return result; 
} 

Vec2i wToRGB(const Vec3f & point) { 
    Mat p3d(point); 
    p3d = extRotation * p3d + extTranslation; 

    float x = p3d.at<float>(0, 0); 
    float y = p3d.at<float>(1, 0); 
    float z = p3d.at<float>(2, 0); 

    Vec2i result; 
    result[0] = (int) round((x * rgbFX/z) + rgbCX); 
    result[1] = (int) round((y * rgbFY/z) + rgbCY); 
    return result; 
} 


void map(Mat& rgb, Mat& depth) { 
    /* intrinsics are focal points and centers of camera */ 
    undistort(rgb, rgb, rgbIntrinsic, rgbDistortion); 
    undistort(depth, depth, depthIntrinsic, depthDistortion); 

    Mat color = Mat(depth.size(), CV_8UC3, Scalar(0)); 
    ushort * raw_image_ptr; 

    for(int y = 0; y < depth.rows; y++) { 
     raw_image_ptr = depth.ptr<ushort>(y); 

     for(int x = 0; x < depth.cols; x++) { 
      if(raw_image_ptr[x] >= 2047 || raw_image_ptr[x] <= 0) 
       continue; 

      float depth_value = depthMeters[ raw_image_ptr[x] ]; 
      Vec3f depth_coord = depthToW(y, x, depth_value); 
      Vec2i rgb_coord = wToRGB(depth_coord); 
      color.at<Vec3b>(y, x) = rgb.at<Vec3b>(rgb_coord[0], rgb_coord[1]); 
     } 
    } 

Nhưng kết quả dường như không thẳng hàng. Tôi không thể thiết lập các bản dịch theo cách thủ công, vì tập dữ liệu thu được từ 3 Kinects khác nhau và mỗi bộ phận đều không được định hướng theo các hướng khác nhau. Bạn có thể thấy một trong đó bên dưới (Trái: biến dạng RGB, Trung: Chiều sâu không bị biến dạng, bên phải: ánh xạ RGB để Depth)

enter image description here

Câu hỏi của tôi là, tôi nên làm gì vào thời điểm này? Tôi đã bỏ lỡ một bước trong khi cố gắng chiếu chiều sâu cho thế giới hoặc thế giới trở lại RGB? Có ai có kinh nghiệm với máy ảnh stereo chỉ ra sai lầm của tôi không?

Cảm ơn bạn rất nhiều trước!

+0

bạn đang sử dụng OpenNI? –

+0

Đáng buồn là không. Chỉ OpenCV –

+0

Tôi đề nghị, bạn nên sử dụng OpenNI để lấy dữ liệu từ Kinect. Có một chức năng sẵn có trong OpenNI có thể làm điều này cho bạn. –

Trả lời

0

OpenCV không có chức năng nào để căn chỉnh luồng độ sâu cho luồng video màu. Nhưng tôi biết rằng có special function có tên là MapDepthFrameToColorFrame trong "Kinect dành cho Windows SDK".

Tôi không có mã ví dụ, nhưng hy vọng rằng đây là điểm tốt để bắt đầu.

Cập nhật: Here is cùng ví dụ về ánh xạ màu ảnh với chiều sâu bằng KinectSDK với giao diện tới OpenCV (không phải mã của tôi).

+0

Đúng như mỗi bài đăng gốc, tôi không thể sử dụng MapDepthFrameToColorFrame (tập dữ liệu là hình ảnh pgm và ppm và tôi không có kinect để làm việc). Và thật đáng buồn những gì tôi thực sự tìm kiếm là các thuật toán nội bộ trong NuiImageGetColorPixelCoordinatesFromDepthPixel, mà tôi không thể tìm thấy ở bất cứ nơi nào (nó không có vẻ như nó là mã nguồn mở) –

1

Tôi cho rằng bạn sẽ cần phải hiệu chỉnh cảm biến độ sâu với dữ liệu RGB theo cùng cách bạn sẽ hiệu chỉnh máy ảnh stereo. OpenCV có một số chức năng (và hướng dẫn) mà bạn có thể tận dụng.

Một vài thứ khác mà có thể hữu ích

  1. http://www.ros.org/wiki/kinect_calibration/technical
  2. https://github.com/robbeofficial/KinectCalib
  3. http://www.mathworks.com/matlabcentral/linkexchange/links/2882-kinect-calibration-toolbox này chứa một bài báo về làm thế nào để làm điều đó.
+0

Ah, tôi đã sử dụng các tham số (máy ảnh nội tại, biến dạng và tham số bên ngoài) mà người dùng khác đã thực hiện hiệu chuẩn trên đó. Vấn đề chính của tôi dường như là sự liên kết, đó có thể là một bước mà tôi đã bỏ lỡ, hoặc như vậy. –

0

Có vẻ như bạn không xem xét giải pháp ngoại lai của mình giữa hai máy ảnh.

0

Có, bạn không xem xét việc chuyển đổi giữa RGB và Độ sâu. Nhưng bạn có thể tính toán ma trận này bằng cách sử dụng phương thức cvStereoCalibrate() mà chỉ truyền các chuỗi hình ảnh của cả RGB và Chiều sâu với các góc bàn cờ vào nó. Các chi tiết mà bạn có thể tìm thấy trong OpecvCV tài liệu: http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#double stereoCalibrate (InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, Kích ImageSize, OutputArray R, OutputArray T, OutputArray E, OutputArray F, TermCriteria tiêu chí, int cờ)

Và phương pháp toàn bộ ý tưởng đằng sau này là:

màu uv < - màu bình thường < - không gian màu < - chuyển đổi DtoC < - chiều sâu không gian < - sâu bình thường hóa < - sâu uv (uc, vc) <-< - ExtrCol * (pc) < - stereo hiệu chỉnh MAT < - ExtrDep^-1 * (pd) <-< (ud - cx) * d/fx, (vd- cy) * d/fy, d> < - (ud, vd)

Nếu bạn muốn thêm biến dạng RGB, bạn chỉ cần làm theo các bước trong: http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html

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