Introduction

본 페이지는 StaticFusion 알고리즘을 돌리기 위해 RGB-D camera (Azure kinect)의 RGB 이미지와 depth 이미지를 png로 저장하는 방법에 대해 설명합니다.

단순히 cv::imwrite() 함수를 이용하여 저장한 후, 이미지를 불러와서 사용하면 될 줄 알았는데, 잘 되지 않음을 확인했습니다.

full code는 여기에서 git clone을 하여 사용하시면 됩니다.

RGB-D Data

ROS에서는 rosbag 내에 RGB data와 depth 이미지를 주로 CompressedImage msg로 제공합니다.

RGB 이미지야, cv::imdecode() 함수로 압축을 풀면 되지만, depth는 그렇지 않습니다.

OpenCV에서 Depth data를 기술하는 방법

data를 cv::Mat으로 기술할 때는 CV_32FC1로 저장하는 방법, CV_16UC1로 저장하는 방법, 이렇게 두가지 방법이 있다.

  • CV_32FC1 (실제 값은 2): float으로, 미터 단위(m)로 기술함.
  • CV_16UC1 (실제 값은 5): unsigned short (uint16_t)로 미리미터 단위(mm)로 기술함. <= 저장공간을 좀 덜 쓰니 이 방식으로 저장된게 아닐까 생각됨

하지만, png 파일로 저장하기 위해서는 필수적으로 CV_16UC1로 기술해야한다 것을 경험적으로 확인했습니다.

위 레포지토리node/src/RGBDSaver.cpp의 65 번 째 줄을 보면, 처음 Azure kinect의 depth를 decode하면 type이 CV_32FC1로 되어 있습니다.

하지만, 이 depth를 cv::write() 함수를 통해 png로 저장한 후, cv::imread() 함수로 다시 불러와보면 data type이 강제로 8UC1로 되는 것을 확인할 수 있습니다. (Note: cv::imread($filename$, -1)로 image를 부르면 이미지 타입을 건드리기 않고 raw한 값을 불러오는데, 그렇게 불러도 강제로 8UC1로 강제로 cast되는 것을 확인했습니다.

따라서 depth data를 png로 저장하기 위해서는 CV_16UC1로 변환을 한 후, cv::write()를 해주어야 합니다.

정리

위 레포지토리node/src/RGBDSaver.cpp 코드 내부에

  • Azure Kinect로부터 얻은 Compressed depth image를 decode하여 cv::MatCV_32FC1로 변환하는 법 (64~65번째 줄)
  • CV_32FC1 -> CV_16UC1로 변환하는 법 (70~81번째 줄)

등이 자세히 적혀 있습니다. :)