从原始RGB深度图像到灰度图的转换不正确

3
我正在使用带深度传感器的Python模拟器进行工作。可视化是用C++完成的。传感器给出以下图像,我需要将其转换为灰度。

Raw Depth

对于转换,我有以下公式:

normalized = (R + G * 256 + B * 256 * 256) / (256 * 256 * 256 - 1)
in_meters = 1000 * normalized

为了在C ++中将图像转换为灰度,我编写了以下代码:

cv::Mat ConvertRawToDepth(cv::Mat raw_image)
{
    // raw_image.type() => CV_8UC3

    // Extend raw image to 2 bytes per pixel
    cv::Mat raw_extended = cv::Mat::Mat(raw_image.rows, raw_image.cols, CV_16UC3, raw_image.data);

    // Split into channels
    std::vector<cv::Mat> raw_ch(3);
    cv::split(raw_image, raw_ch); // B, G, R

    // Create and calculate 1 channel gray image of depth based on the formula
    cv::Mat depth_gray = cv::Mat::zeros(raw_ch[0].rows, raw_ch[0].cols, CV_32FC1);
    depth_gray = 1000.0 * (raw_ch[2] + raw_ch[1] * 256 + raw_ch[0] * 65536) / (16777215.0);

    // Create final BGR image
    cv::Mat depth_3d;
    cv::cvtColor(depth_gray, depth_3d, cv::COLOR_GRAY2BGR);

    return depth_3d;
}

实现下一个结果:

Cpp Depth

如果我在Python中进行转换,我可以简单地编写:
def convert_raw_to_depth(raw_image):
    raw_image = raw_image[:, :, :3]
    raw_image = raw_image.astype(np.float32)
    
    # Apply (R + G * 256 + B * 256 * 256) / (256 * 256 * 256 - 1).
    depth = np.dot(raw_image, [65536.0, 256.0, 1.0])
    depth /= 16777215.0  # (256.0 * 256.0 * 256.0 - 1.0)
    depth *= 1000
    
    return depth

实现下一个结果:

enter image description here

很明显,在Python中做得更好,但公式是相同的,图像也是相同的,那么为什么会有差异,我该如何重写C++代码以获得与Python类似的结果?


raw_image 是哪种像素格式?如果它不是每个通道16位,那么你的 CV_16UC3 就没有太多意义。如果它是每个通道16位,那么你乘以256和256 x 256也没有太多意义。 - Micka
2
@Micka 该评论表示 raw_image.type() => CV_8UC3 - MikeCAT
@Micka 我们之前就看到过了。它将24位深度分成三个字节,然后将每个字节放入一个颜色通道中。给定的方程式揭示了这一点。 - Christoph Rackwitz
@ChristophRackwitz 但是对于CV_16UC3代码来说,这并没有太多意义。如果输入为16uc3,则我会期望2^0、2^16和2^32作为乘数。 - Micka
2
我不知道OP在16UC3方面在想什么,这毫无意义。OP并不一定知道自己在做什么,这种假设通常是错误的。raw_extended也从未被使用,因此它是无关紧要的。 - Christoph Rackwitz
1个回答

3

看起来你正在处理Python中的np.float32数组,而在C++中则是CV_8UC3数组。

尝试在计算之前转换为CV_32FC3

    // Convert to float and split into channels
    cv::Mat raw_image_float;
    raw_image.convertTo(raw_image_float, CV_32FC3);
    std::vector<cv::Mat> raw_ch(3);
    cv::split(raw_image_float, raw_ch); // B, G, R

"depth_gray" 矩阵的类型为 CV_32FC1,计算完成后,我期望结果为浮点数并正确保存。我已经测试过了,它像Python中的一样工作良好!谢谢! - GabyUnalaq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接