OpenCV - 16bit unsigned int 깊이 이미지 저장하기/불러오기

OpenCV - 16bit unsigned int 깊이 이미지 저장하기/불러오기

깊이 이미지를 저장할때 각 pixel마다 미터단위로 저장하면 소수점으로 표현해야하므로 float형으로 저장해야한다. 그렇게 되면 낭비되는 메모리가 많으므로 보통은 밀리미터 단위로 저장한다. 즉, 16bit unsigned int(uint16_t)형을 주로 사용해 저장하게 된다. 물론 사용할 때는 다시 프로그램에서 원하는 단위로 변경해주면 된다.

RGB이미지와는 포맷이 다르므로 OpenCV를 이용해 저장하거나 불러올때 약간 다르다. 깊이 이미지는 libRealsense를 이용해 받는다고 가정한다.


  • 저장하기

1
2
3
4
5
cv::Mat depth(480640, CV_16U, (uint16_t*)dev->get_frame_data(rs::stream::depth_aligned_to_color));
std::vector<int> param;
param.push_back(CV_IMWRITE_PNG_COMPRESSION);
param.push_back(0);
cv::imwrite("depthimage.png",depth,param);
cs

저장 parameter를 vector로 넘겨준다. 자세한 옵션들과 사항들은 http://docs.opencv.org/3.0-beta/modules/imgcodecs/doc/reading_and_writing_images.html 에서 확인할 수 있다.


  • 불러오기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cv::Mat dep_img(cv::imread("depthimage.png", CV_LOAD_IMAGE_ANYDEPTH));
if (!dep_img.data) {
    std::cout << "No " << path << " image." << std::endl;
    exit(-1);
}
cv::Mat dep_img_meter(dep_img.size().height, dep_img.size().width, CV_32F);
dep_img.convertTo(dep_img, CV_16U);
//uint16 --> float (mm->m)
for (int u = 0; u < color_size_height_; u++){
    for (int v = 0; v < color_size_width_; v++){
        int idx = v + u*color_size_width_;
        dep_img_meter.at<float>(u, v) = (1.0f / 1000.0f)*dep_img.at<uint16_t>(u, v);
    }
}
cs

마찬가지로 위의 링크에서 자세한 내용들을 확인 할 수 있다. 읽어올 때 RGB인지 RGBA인지 깊이 이미지처럼 1개의 채널만 가지고 있는지 알려주는 parameter가 있다. 1개의 채널만 있는 깊이 이미지이므로 CV_LOAD_IMAGE_ANYDEPTH파라미터를 넣었다. 기본적으로 이미지를 8비트단위로 끊어 읽는다. 그런데 이 이미지는 저장할 때 unsigned 16비트형으로 저장되어 있었기 때문에 convetTo로 포멧을 변형 시켜 읽는다. 자세한 사항들은 역시 Opencv 레퍼런스에 나와있다.
http://docs.opencv.org/2.4/doc/tutorials/introduction/display_image/display_image.html