【问题标题】:Save float * images in C++在 C++ 中保存浮点 * 图像
【发布时间】:2013-08-04 06:47:54
【问题描述】:

我想了解如何保存float 类型的图像:

float * image;

以这种方式分配:

int size = width * height;
image = (float *)malloc(size * sizeof(float));

我尝试使用 CImg 库,但不直接接受浮点数。事实上,我只用它来捕捉图像浮动,因为我只需要浮动图像。

CImg<float> image("image.jpg");
int width = image.width(); 
int height = image.height();
int size = width*height
float * image = image.data();

如何将这张图片从.jpg.bmp 保存到float 可读。我想打开一个写缓冲区,但没有保存任何东西,我无法从文件中读取!

【问题讨论】:

  • 这些图片来自哪里?什么是浮点范围?我几乎可以肯定您需要先将格式标准化为整数值。

标签: c++ serialization floating-point cimg


【解决方案1】:

嗯,您首先需要了解您要做什么。 您正在创建一个指向浮点数组的指针

image=(float *)malloc(size* sizeof(float));

然后你在做

float * image =image.data();

这是对image 的双重使用,这将导致编译器错误,并且如果可以的话,也是一件坏事。

现在您应该继续阅读 CImg here 并看到 Data() 返回指向图像第一个像素的指针。

现在我们已经确定了所有这些,让我们来看看解决方案: 如果要将浮点数组保存到文件中,请使用此示例

#include <fstream.h>

void saveArray(float* array, int length);

int main()
{
    float image[] = { 15.25, 15.2516, 84.168, 84356};
    saveArray(floatArray, sizeof(image)/ sizeof(image[0]));

    return 0;
}

void saveArray(float* array, int length)
{
    ofstream output("output.txt");

    for(int i=0;i<length;i++)
    {
        output<<array[i]<<endl;
    }
}

【讨论】:

  • 您好,谢谢您的回答。除了一件事,大家都很清楚:为什么 output.txt 是 txt 而不是 bmp 或 jpg?
  • 因为我仍然不知道你的目的......你以.jpg开头,所以我不知道你为什么要打开它然后再次保存......如果你想复制它有更简单的方法
  • 好的,我会告诉你,我想打开一个图像,将它传递给浮动应用我制作的算法,然后以可读格式将此浮动保存在我的目标文件夹中;-)
  • 我不确定 bmp/jpg 文件的格式,但我很确定您可以通过简单的 google 搜索找到所需的所有信息。我这么说是因为我现在没有时间检查它,但如果你想等几个小时,我会有时间的。
【解决方案2】:

由于 JPEG 图像格式仅支持 8 位颜色分量(实际上标准允许 12 位,但我从未见过它的实现),因此您无法使用 JPEG 执行此操作。

您可以使用 .bmp 文件执行此操作。请参阅我的answer to a question,了解使用OpenCV 库的可能方法。对于其他一些库,使用 .bmp 文件可能很容易,因为 OpenCV 假定 8 位颜色通道,尽管据我所知,.bmp 格式并没有规定。

您需要压缩吗?如果不只是写一个二进制文件,或者以yml格式存储文件等等。

如果您需要压缩OpenEXR 可以考虑。 Image Magick 可能是您的最佳实现,因为它与 CImg 集成得很好。由于 CImg 本身不支持 .jpg,我怀疑您可能已经拥有 Image Magick。

【讨论】:

  • BMP 文件格式(他们可以接受)没有压缩,所以他们可能不需要压缩。
  • 嗨,实际上我不想在这个应用程序中使用 OpenCv,因为根据我的观点,lib 太重了:-(
  • @user2485282 我不确定您认为 OpenCV 有什么问题 - 根据我的经验,它真的很快。如果由于某种原因您不想安装整个库,您可以随时仅复制 .bmp 编解码器的源代码。
  • 你可能是对的,但除了 OpenCv 我找不到任何库来做这件事!我想真正理解执行此操作的代码而不是使用库
【解决方案3】:

嗯,我可以从您的代码中看到您仅使用 32 位浮点灰度(没有 R、G、B 只是我) 所以这是我的建议:

  1. Radiance RGBE (.hdr) 将 3x8 位尾数用于 R、G、B 和 1x8 位指数,它只提供 16 位精度。 但是,如果您还使用 R、G、B 而非出于模拟目的,则此格式不适合您。 (因为所有通道的指数都是相同的,所以你会非常精确)

  2. 任何 HDR 格式都不是原生格式,因此您需要安装查看器,并且必须为您的源代码编写读/写函数或使用库

  3. 非 HDR 格式(bmp、jpg、tga、png、pcx...) 如果您只使用灰度,那么这对您来说是最好的解决方案。这些格式通常是每个通道 8 位,因此您可以将 24-32 位一起用于您的单一强度。您还可以在大多数操作系统上本地查看/编辑这些图像。有两种方法可以做到这一点。

    • 对于 32 位图像,您可以简单地将浮点数复制到颜色 =((DWORD*)(&col))[0];其中 col 是您的浮点像素。这是最简单的,没有精度损失,但是如果您查看图像,它会不漂亮:) 因为浮点数的存储方式与整数类型不同。

    • 使用调色板。创建从像素颜色的最小到最大可能值的色阶调色板(保存的颜色越多,精度越高)。然后将整个图像绑定到这个值。在此之后将浮点值转换为调色板中的索引并将其存储(用于保存)并从颜色(用于加载)的调色板中的索引中反向获取浮点数,以这种方式,图片将类似于热图像...从浮点数转换索引/RGB 颜色的值可以线性(降低很多精度)或非线性(通过 exp、log 函数或您想要的任何非线性)在最好的情况下,如果您使用 24 位像素并从所有 2^24 种颜色中获得比例调色板并且您使用非线性转换比你只损失 25% 的精度(如果你真的使用浮点的整个动态范围,如果不是比损失更小甚至为零)

缩放提示:

  • 看一下光谱颜色,它是一个很好的开始色标(有许多简单的源代码可以用一些 fors 只是谷歌创建这个),你也可以使用任何颜色渐变模式。

  • 非线性函数应该在需要保持精度的浮点范围(大多数像素可以在的范围)上变化较小,而在精度不重要的地方(+/- NaN)变化很大。我通常使用 exp、ln 或 tan,但您必须将它们缩放到您的调色板范围。

【讨论】:

    【解决方案4】:

    BMP 文件格式非常简单: https://en.m.wikipedia.org/wiki/BMP_file_format

    读取标头以确定高度、宽度、bpp 和数据起始索引。然后通过将像素通道值转换为浮点数(从标题中指定的索引开始)开始填充浮点数组,跨越宽度。当你到达指定宽度的模块时,转到数组中的下一行。

    JPG 解码更复杂。我建议不要自己动手。

    【讨论】:

      【解决方案5】:

      如果要保存浮点值,则需要使用支持它们的格式——不是 JPEG 也不是 BMP。最可能的选择是:

      • TIFF - 需要一个库来编写

      • FITS——主要用于天文数据,写起来不难

      • PFM(便携式浮点格式)是最小公分母格式,与NetPBM format 相同,在here 中描述。

      好消息是 CImg 支持 PFM 开箱即用,无需额外的库。所以你的问题的答案很简单:

      #include "CImg.h"
      using namespace cimg_library;
      int main() {
         CImg<float> image("image.png");
         image.normalize(0.0,1.0);
         image.save_pfm("result.pfm");
      }
      

      如果您想稍后查看您的图像,ImageMagick 可以理解上述所有格式,并且可以将其中的任何格式转换为其他格式:

      convert result.pfm image.jpg       # convert PFM to JPG
      convert result.pfm image.png       # convert PFM to PNG
      convert result.tif image.bmp       # convert TIF to BMP
      

      关键字:CImg、C++、C、浮点、浮点、图像、图像处理、另存为浮点、真实、另存为真实、32 位、PFM、便携式浮点映射

      【讨论】:

      • CImg 本身可以将 pfm 文件转换成另一种格式?
      猜你喜欢
      • 1970-01-01
      • 2018-10-23
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-10
      • 1970-01-01
      • 1970-01-01
      • 2011-01-18
      相关资源
      最近更新 更多