我在-32768和32767之间有一个16位样本。 为了节省空间,我想将其转换为8位样本,因此我将样本除以256,并添加128.
-32768 / 256 = -128 + 128 = 0
32767 / 256 = 127.99 + 128 = 255.99
现在,0将完全适合一个字节,但255.99必须向下舍入到255,导致我的精度松散,因为转换回来时我将得到32512而不是32767。
如何在不丢失原始最小/最大值的情况下执行此操作?我知道我犯了一个非常明显的思想错误,但我无法弄清楚错误所在。
是的,当然我完全清楚我通过划分失去了精度,并且无法从8位样本中推导出原始值,但我只是想知道为什么我没有得到原始最大值。 / p>
答案 0 :(得分:1)
已经提供了下采样的答案。
这个答案涉及使用全范围的上采样。这是一个C99代码段,演示如何在整个值范围内传播错误:
#include <stdio.h>
int main(void)
{
for( int i = 0; i < 256; i++ ) {
unsigned short scaledVal = ((unsigned short)i << 8) + (unsigned short)i;
printf( "%8d%8hu\n", i, scaledVal );
}
return 0;
}
这很简单。您将值左移8,然后再添加原始值。这意味着[0,255]范围内每增加1对应于[0,65535]范围内增加257。
我想指出,这可能会比你开始时效果更差。例如,如果您对65280(0xff00)进行下采样,则会得到255,但是然后进行上采样会得到65535(0xffff),这是总错误255.在数据范围的大部分高端,您将遇到类似的大错误。
你可能会更好地放弃回到[0,65535]范围的概念,而是将你的值减半。也就是说,向左移动并添加127.这意味着错误是均匀的而不是倾斜的。因为您实际上并不知道原始值是什么,所以您可以做的最好的事情是使用正中值来估计它。
总而言之,我认为这在数学上更正确:
unsigned short scaledVal = ((unsigned short)i << 8) + 127;
答案 1 :(得分:0)
您没有获得原始最大值,因为您不能将数字256表示为8位无符号整数。
答案 2 :(得分:0)
如果您尝试将16位整数值压缩为8位整数值范围,则取最重要的8位并保留它们,同时丢弃最低8位。通常,这是通过移位来完成的。 >>
运算符是从最高位到最低位的转换,如果使用8次或>>8
则可以工作。您也可以屏蔽掉字节并在分割之前将00舍入为舍入,例如8BitInt =(16BitInt&amp; 65280)/ 256; [65280 a.k.a 0xFF00]
你从一个值偏移的每一位都将它减半,比如除以2,然后向下舍入。
由于您正在处理有符号整数,所以上述所有内容都很复杂。
最后我并非100%肯定我在这里得到了一切,因为我真的没有尝试过这样做。