Search code examples
opencvros

Converting depth image from millimeter to meters in OpenCV


This seems really easy but I am getting an error with OpenCV image processing. The input image is a depth image having CV_16UC1 encoding (depth values are in millimeter). I want to convert depth values to meters as shown below-

auto img_m = img_mm * 0.001f; // convert to meter (SI units)

Finally, I need depth values of a few pixels. Therefore, I am using the mat.at() function in the following way-

// let say we want to get the depth value at (0, 0)
int pixel_x = 0;
int pixel_y = 0;
auto depth = img_m.at<unsigned short>(pixel_y, pixel_x);

Unfortunately, it is showing the following compilation error-

error: ‘class cv::MatExpr’ has no member named ‘at’
       auto depth = img_m.at<unsigned short>(pixel_y, pixel_x);

Out of curiosity, I checked the data type of both the images and found the following-

std::cout << "cvtype(img_mm): " << img_mm.type() << std::endl;
std::cout << "size(img_mm): " << img_mm.size() << " size(img_m): " << img_m.size() << std::endl;
std::cout << "type(img_mm): " << typeid(img_mm).name() << " type(img_m): " << typeid(img_m).name() << std::endl;

cvtype(img_mm): 2
size(img_mm): [640 x 480] size(img_m): [640 x 480]
type(img_mm): N2cv3MatE type(img_m): N2cv7MatExprE

Here, we can see that img_m is N2cv7MatExprE, which is causing the compilation error.

As a workaround, instead of converting img_mm to img_m, I am multiplying the depth value as following-

auto depth_mm = img_mm.at<unsigned short>(pixel_y, pixel_x);
auto depth_m = depth_mm * 0.001f; // convert to meter (SI units)

However, I want to know why scalar multiplication is going crazy!!!

Below are the environment details-

  • Ubuntu 14.04 LTS OS
  • ROS Indigo (Default OpenCV shipped along ROS)
  • OpenCV 2.4.8
  • CMAKE_CXX_COMPILER_VERSION 4.8.5

Solution

  • You are using auto to let compiler deduce the type for img_m and compiler deduces it correctly as cv::MatExpr. Multiplying cv::Mat and a sclalar results in cv::MatExpr that can be casted to cv::Mat. To avoid this problem you should specify the type for img_m:

    cv::Mat img_m = img_mm * 0.001f; // convert to meter (SI units)