【问题标题】:How do you convert a 16 bit unsigned integer to a larger 8 bit unsigned integer?如何将 16 位无符号整数转换为更大的 8 位无符号整数?
【发布时间】:2015-08-19 20:35:41
【问题描述】:

我有一个函数需要返回一个 16 位无符号整数向量,但对于另一个我也称之为这个函数的函数,我需要 8 位无符号整数向量格式的输出。例如,如果我开始:

std::vector<uint16_t> myVec(640*480);

如何将其转换为以下格式:

std::vector<uint8_t> myVec2(640*480*4);

更新(更多信息): 我正在使用 libfreenect 及其 getDepth() 方法。我已经修改它以输出一个 16 位无符号整数向量,以便我可以检索以毫米为单位的深度数据。但是,我还想显示深度数据。我正在使用 freenect 安装中的一些示例代码 c++,它使用 glut 并且需要 8 位无符号整数向量来显示深度,但是,我需要 16 位来检索以毫米为单位的深度并将其记录到文本文件中。因此,我希望在 glut 的 draw 函数中将数据检索为 16 位无符号整数向量,然后将其转换,以便我可以使用已经编写的 glut 函数显示它。

【问题讨论】:

  • 需要更多信息。 8 位值与 16 位值有何关系?
  • 如果不复制数据(即您想重新分配所有权并重新解释底层缓冲区的类型),这非常困难,因为std::vector 没有公开任何外部覆盖其内部缓冲区的方法指针。
  • 您想要做的不仅仅是将 16 位数字转换为 8 位数字,请参阅我的答案了解更多信息
  • 所以你在 both 向量中有相同数量的值,对吧?如何将单个值从 16 位转换为 8 位?它们是否需要以某种方式缩放?最大 16 位值是否需要映射到最大 8 位值(例如)?
  • @Galik 他做到了,这就是我在回答中的意思。他需要某种亮度传递函数来将他的数据集映射为在图像中具有某种含义的值。

标签: c++


【解决方案1】:

根据您的更新,假设 8 位 unsigned int 将显示为灰度图像,您需要的类似于亮度传递函数。基本上,您的输出函数希望将数据映射到值 0-255,但您不一定希望这些值直接对应于毫米。如果您的所有数据都来自 0-3 毫米怎么办?然后你的图像看起来几乎是全黑的。如果都是300-400mm怎么办?然后它将是完全白色的,因为它被剪裁为 255。

一种基本的方法是找到最小值和最大值,然后这样做:

double scale = 255.0 / (double)(maxVal - minVal);
for( int i = 0; i < std::min(myVec.size(), myVec2.size()); ++i )
{
    myVec2.at(i) = (unsigned int)((double)(myVec.at(i)-minVal) * scale);
}

根据您的数据分布,您可能需要做一些更复杂的事情来充分利用您的动态范围。

编辑:这假设您的 glut 函数正在创建图像,如果它使用 8 位值作为图形的输入,那么您可以忽略。

Edit2:您的其他更新之后的更新。如果你想填充一个 640x480x4 的向量,你显然是在做一个图像。你需要做我上面概述的事情,而且它正在寻找的 4 个维度是红色、绿色、蓝色和 Alpha。 Alpha 通道需要始终为 255(这控制它的透明度,您不希望它透明),至于其他 3...您从上面的函数中获得的值(缩放值)如果将所有 3 个通道(通道为红色、绿色和蓝色)设置为相同的值,它将显示为灰度。例如,如果我的数据范围为 0-25mm,对于值为 10mm 的像素,我会将数据设置为 255/(25-0)* 10 = 102,因此像素将为 (102, 102, 102,第255章)

编辑 3:添加关于亮度传递函数的维基百科链接 - https://en.wikipedia.org/wiki/Color_mapping

【讨论】:

    【解决方案2】:

    如何将其转换为以下格式:

    std::vector myVec2;这样 myVec2.size() 将是两倍 和 myVec.size() 一样大吗?

    myVec2.reserve(myVec.size() * 2);
    for (auto it = begin(myVec); it!=end(myVec); ++it)
    {
        uint8_t val = static_cast<uint8_t>(*it); // isolate the low 8 bits
        myVec2.push_back(val);
        val = static_cast<uint8_t>((*it) >> 8); // isolate the upper 8 bits
        myVec2.push_back(val);
    }
    

    或者您可以更改push_back() 的顺序,前提是哪个字节在前(高位或低位)。

    【讨论】:

      【解决方案3】:

      直截了当:

      std::vector<std::uint8_t> myVec2(myVec.size() * 2);
      std::memcpy(myVec2.data(), myVec.data(), myVec.size());
      

      或使用标准库

      std::copy( begin(myVec), end(myVec), begin(myVec2));
      

      【讨论】:

      • 这个结果会取决于机器的字节序吗?
      • @triple_r 是的,它会,但不清楚操作员打算如何解释数据......如果他在具有相同字节序的机器上撤消操作,那没关系。
      • @triple_r 会,但正如 RyanP 所说,它并没有真正指定。 std::copy 不应该有这个问题,我想。
      • 是的,你是对的。我只是好奇memcpy 会发生什么。
      猜你喜欢
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      相关资源
      最近更新 更多