我正在运行此处的教程:https://software.intel.com/en-us/articles/using-librealsense-and-opencv-to-stream-rgb-and-depth-data
它使用以下几行从r200获取深度值:
cv::Mat depth16( _depth_intrin.height, _depth_intrin.width, CV_16U,(uchar *)_rs_camera.get_frame_data( rs::stream::depth ) );
cv::Mat depth8u = depth16;
depth8u.convertTo( depth8u, CV_8UC1, 255.0/1000 );
imshow( WINDOW_DEPTH, depth8u );
输出的图像流为:
您也可以看到彩色图像。我还在卷尺的底部放了一个卷尺,最大可以达到3.5m(r200的范围应该达到3.5m)
为什么地球上的颜色是二进制的?我尝试添加不同的彩色图像,但似乎根本不是深度值。同样,即使地板从1m到5m的距离,地板始终是黑色也没有意义。为什么所有物体都是白色的?桌子和沙发显然距离不同。
我该如何改善?我知道您可以从r200中获得良好的深度值,就像我在示例中得到的那样。参见(http://docs.ros.org/kinetic/api/librealsense/html/cpp-capture_8cpp_source.html),但是它们使用的是glfw而不是OpenCV。我想知道为什么深度值一旦转换就这么奇怪。
理想情况下,我想生成深度值并过滤1m至2m范围之外的任何值。谢谢!
答案 0 :(得分:1)
编辑:正如@MSalters指出的那样,我的答案的前半部分是错误的,并且是由于我对OP代码的错误理解。后半部分包含正确的答案。
如果您的深度范围是1-3.5m,则以毫米(1000mm-3500mm)为单位;将结果除以1000,将得到的数据范围为1.0-3.5。但是,您的源数据是16位无符号类型,不能表示十进制或浮点值,只能表示整数,因此您的值将被截断为{0,1,2,3}之一。您可能在 convertTo
中不使用此方法,因为它可能会在内部封送类型,但这是潜在的错误来源。
尽管有第二个问题... CV_8U
是一个8位无符号字符,它也只能表示整数值,这次的范围是0-255。由于您的数据可以在0 ... 3500的范围内,因此您可以像示例中那样将其乘以0.255,因此,深度超过1000mm的任何值都会导致值超过255,并在那里被截断。
您可以使用cv::normalize函数和NORM_MINMAX
归一化类型来将数据归一化到0 ... 255范围,而不是像上面那样转换原始深度图像。您也可以将目标图像格式设置为CV_8U。
这可能仅适用于可视化,因为它会受到源数据输入范围的影响。相反,如果您知道最大值是3500,而最小值是0,则将源图像除以3500,然后乘以255。也就是说,在可能的情况下,最好将其保留为16位格式深度分辨率。