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 shortfloat转换数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的分割只是为了校正单位(可能是毫米或毫米),或者它是某种固定点语义。 (整数数据类型中的有理数的重新排序)。

+1

感谢您的强有力,明智的答案。我已经联系了作者,但至今没有回复。一旦找到答案,我会发布解决方案... – mcExchange