我正在尝试理解一个corcel package,它读取并转换存储为16位png文件的深度数据。
首先,他们将文件加载到类型为CV_16UC1
cv::Mat depth_image = cv::imread(filename.c_str(), CV_LOAD_IMAGE_ANYDEPTH);
然后他们分配
unsigned short * depth_raw = new unsigned short[frame_height * frame_width];
for (int i = 0; i < frame_height * frame_width; ++i) {
depth_raw[i] = ((((unsigned short)depth_image.data[i * 2 + 1]) << 8) + ((unsigned short)depth_image.data[i * 2 + 0]));
depth_raw[i] = (depth_raw[i] << 13 | depth_raw[i] >> 3);
depth_data[i] = float((float)depth_raw[i] / 1000.0f);
}
现在我知道“&lt;&lt;” C ++中的运算符类似于位移,意味着5 << 1
对应于下面的位移:“00000101”(二进制为5) - &gt; “00001010”(二进制为10)。因此,人们可以使用“&lt;&lt;&lt; n”或“&gt;&gt; n”进行乘法和除法2 ^ n。
我仍然觉得很难理解上面的转变。以下是针对上述转换的数字示例(将cout
应用于每个步骤):
depth_image.data[i] = 192
depth_image.data[2*i+1] = 47
depth_image.data[2*i+0] = 192
(((unsigned short)depth_image.data[i * 2 + 1]) << 8) = 12032
((unsigned short)depth_image.data[i * 2 + 0]) = 192
depth_raw[i] = 12224
depth_raw[i] << 13 = 0
depth_raw[i] >> 3 = 191
depth_raw[i] << 13 | depth_raw[i] >> 3 = 191
depth_data[i] = 1.528
真正奇怪的是最后一行:似乎从unsigned short
到float
的转换将数字191转换为1528 ???
任何帮助或提示都将受到赞赏。
编辑:
我找到了一些Matlab代码,显示了作者之前如何保存深度图像:
% resave depth map with bit shifting
depthRaw = double(imread(filename))/1000;
saveDepth (depthRaw,newFilename);
function saveDepth (depth,filename)
depth(isnan(depth)) =0;
depth =single(depth)*1000;
depthVis = uint16(depth);
depthVis = bitor(bitshift(depthVis,3), bitshift(depthVis,3-16));
imwrite(depthVis,filename);
end
所以它看起来像一个奇怪的拯救......
EDIT2:
作者的回复:
“深度图的保存方式是它可以移动3位,使PNG格式的深度更加令人赏心悦目。因此我们需要在文件读取过程中将其移回”。
答案 0 :(得分:3)
没有共同的规范,数据是如何存储的。因此,可能需要从小端转换为大端或相反的方式。要了解endianess,请查看此处:https://en.wikipedia.org/wiki/Endianness
depth_raw[i] = ((((unsigned short)depth_image.data[i * 2 + 1]) << 8) + ((unsigned short)depth_image.data[i * 2 + 0]));
此声明是字节序的转换。第一个字节转换为无符号短路(从8位到16位),然后向右移动,然后在低端添加第二个字节。它基本上交换了两个字节并将其转换为unsigned int。
depth_raw[i] = (depth_raw[i] << 13 | depth_raw[i] >> 3);
depth_data[i] = float((float)depth_raw[i] / 1000.0f);
在转换endianess之后,必须解释数据。确定作者打算在这里做的唯一方法是查看深度图的文档。第一行将3个最低有效位移到前面,其他位向下移动。我不知道,为什么要这样做。我认为在此之后除以1000只是为了校正单位(可能是m或mm中的m或m),或者它是某种固定点语义。 (在整数数据类型中重新理解有理数)。