C++中的按位数学运算
我想了解function,它读取和转换以16位png文件存储的深度数据。C++中的按位数学运算
首先,他们将文件加载到类型的OpenCV的垫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);
}
现在我知道,在C++中的“< <”操作是一样的东西有点移位,意思是对应于以下移位:“00000101”(二进制数为5) - >“00001010”(二进制数为10)。因此,显然可以使用“< < n”或“>> 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格式的深度更加令人满意,因此我们需要在文件读取期间将其移回。
有没有共同的规范,如何存储数据。因此可能需要从小到大或从其他方式转换。要了解字节序看看这里: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);
经过转换后,数据必须被解释。确定作者在这里要做的唯一方法是查看深度图的文档。第一行将3个最不重要的位移到前面,其他的向下移动。我不知道,为什么这样做。我认为在此之后1000的分割只是为了校正单位(可能是毫米或毫米),或者它是某种固定点语义。 (整数数据类型中的有理数的重新排序)。
感谢您的强有力,明智的答案。我已经联系了作者,但至今没有回复。一旦找到答案,我会发布解决方案... – mcExchange