2

我想了解如何保存类型的图像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();

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

4

5 回答 5

0

好吧,我可以从您的代码中看到您仅使用 32 位浮点灰度(只有 I 没有 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,但您必须将它们缩放到您的调色板范围。

于 2013-08-04T08:51:17.397 回答
0

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

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

然后你在做

float * image =image.data();

如果可以的话,这是双重使用image会导致编译器错误和一件坏事。

现在你应该继续阅读CImg 这里并看到它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;
    }
}
于 2013-08-04T07:10:31.260 回答
0

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

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

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

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

于 2013-08-04T07:15:47.270 回答
0

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

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

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

于 2015-08-05T00:52:58.273 回答
0

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

  • TIFF - 需要一个库来编写

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

  • PFM(便携式浮点格式)是最小公分母格式,与NetPBM 格式相同,在此处进行了描述。

好消息是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、便携式浮点图

于 2017-08-20T20:43:05.833 回答