加快写入多个图像 TIFF?
Speed up writing multiple image TIFF?
我正在尝试将图像堆栈写入 TIFF 文件。图像大小为 256*256 像素,每个堆栈包含 1000 张图像。编写其中一个文件大约需要 4 分钟 - 所以我的代码很可能有问题。
这是我正在做的事情:
void Tiff_WriterSplit(float data[], int PicNum, int WIDTH, int LENGTH, char PATH[]) {
int i;
int rows = LENGTH, columns = WIDTH;
TIFF* tif;
if (PicNum == 0)
tif = TIFFOpen(PATH, "w");
else
tif = TIFFOpen(PATH, "a");
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, columns);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, rows);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
for (i = 0; i < rows; i++)
TIFFWriteScanline(tif, &data[i * columns], i, 0);
TIFFWriteDirectory(tif);
TIFFClose(tif);
}
将为堆栈中的每个图像调用此函数Tiff_WriterSplit
。第一个图像将有 PicNum = 0
以 w
模式打开 tiff 文件,以下所有图像将有一个 PicNum > 0
以 a
模式打开它。写这个从大约 40 MB/s 开始,随着文件大小的增加变得越来越慢 - 下降到大约 1 MB/s。如何优化性能?
我遇到过类似的性能问题。似乎(从 libTiff 版本 4.0.9 开始)TIFFWriteDirectory 中存在性能问题,导致其 运行 时间与多页 TIFF 文件中已存在的图像数量成比例。
我认为这与 TIFF 文件规范的编写方式无关 - 我认为这是 libTiff 中的性能错误。
我发现保存前 80 张图像(大约 24,000 字节)需要 21 毫秒,但当我将 9,000 张图像写入同一个文件时,这个时间线性上升到 3 秒。 99.5% 的时间花在 TIFFWriteDirectory 中(调用 TIFFLinkDirectory,大部分时间花在 _tiffReadProc 中)。
写 tiff 比读 tiff 容易多了。 libtiff 的开销对于写入性能可能非常有限。假设你有一个可以用 tiff header 表示的像素格式的缓冲区,编写 tiff 的步骤,
- 写 tiff header
- 写入图像数据
- 写入目录(标签table)。
对于 multi-image tiff,我们受到 32 位条目的 4GB tiff 限制。但是,如果您的图像始终具有相同的几何形状(宽度、高度、平面、深度),则可以在写入所有图像数据后写出标记 table 中的目录条目。您可以随意将目录放在 tiff 二进制文件的末尾(或开头)。如果最后你知道图像的数量,你可以在写入图像之前形成目录条目(就地构造 table)。如果API不允许你事先知道图像的数量,那么最终的文件偏移量必须在写入最终图像后在IFD中计算。
直接编写 tiff 可以让您使用 fallocate
、mmap
和其他 OS 功能,这些功能可以加快编写 multi-image tiff 的速度。如果需要转换图像格式,则这项工作在计算上更具挑战性,因为它可能涉及信号处理。
与 libtiff 相比,直接写入的单图像平面写入速度可以快 3 倍以上。如果 libtiff 不断地重新计算和重新定位标签 table 在 tiff (IFD) 的末尾,那么这将是每个图像的 O(n^2)。
我使用此技术将科学图像传感器数据从 genicam 设备流式传输到磁盘。它允许以更高的 FPS 进行捕获。
将视觉分析与 multi-tiff(目录)结构相结合,可以在单个 tiff 中为每个帧保存多个感兴趣区域。
参考
我正在尝试将图像堆栈写入 TIFF 文件。图像大小为 256*256 像素,每个堆栈包含 1000 张图像。编写其中一个文件大约需要 4 分钟 - 所以我的代码很可能有问题。
这是我正在做的事情:
void Tiff_WriterSplit(float data[], int PicNum, int WIDTH, int LENGTH, char PATH[]) {
int i;
int rows = LENGTH, columns = WIDTH;
TIFF* tif;
if (PicNum == 0)
tif = TIFFOpen(PATH, "w");
else
tif = TIFFOpen(PATH, "a");
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, columns);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, rows);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
for (i = 0; i < rows; i++)
TIFFWriteScanline(tif, &data[i * columns], i, 0);
TIFFWriteDirectory(tif);
TIFFClose(tif);
}
将为堆栈中的每个图像调用此函数Tiff_WriterSplit
。第一个图像将有 PicNum = 0
以 w
模式打开 tiff 文件,以下所有图像将有一个 PicNum > 0
以 a
模式打开它。写这个从大约 40 MB/s 开始,随着文件大小的增加变得越来越慢 - 下降到大约 1 MB/s。如何优化性能?
我遇到过类似的性能问题。似乎(从 libTiff 版本 4.0.9 开始)TIFFWriteDirectory 中存在性能问题,导致其 运行 时间与多页 TIFF 文件中已存在的图像数量成比例。
我认为这与 TIFF 文件规范的编写方式无关 - 我认为这是 libTiff 中的性能错误。
我发现保存前 80 张图像(大约 24,000 字节)需要 21 毫秒,但当我将 9,000 张图像写入同一个文件时,这个时间线性上升到 3 秒。 99.5% 的时间花在 TIFFWriteDirectory 中(调用 TIFFLinkDirectory,大部分时间花在 _tiffReadProc 中)。
写 tiff 比读 tiff 容易多了。 libtiff 的开销对于写入性能可能非常有限。假设你有一个可以用 tiff header 表示的像素格式的缓冲区,编写 tiff 的步骤,
- 写 tiff header
- 写入图像数据
- 写入目录(标签table)。
对于 multi-image tiff,我们受到 32 位条目的 4GB tiff 限制。但是,如果您的图像始终具有相同的几何形状(宽度、高度、平面、深度),则可以在写入所有图像数据后写出标记 table 中的目录条目。您可以随意将目录放在 tiff 二进制文件的末尾(或开头)。如果最后你知道图像的数量,你可以在写入图像之前形成目录条目(就地构造 table)。如果API不允许你事先知道图像的数量,那么最终的文件偏移量必须在写入最终图像后在IFD中计算。
直接编写 tiff 可以让您使用 fallocate
、mmap
和其他 OS 功能,这些功能可以加快编写 multi-image tiff 的速度。如果需要转换图像格式,则这项工作在计算上更具挑战性,因为它可能涉及信号处理。
与 libtiff 相比,直接写入的单图像平面写入速度可以快 3 倍以上。如果 libtiff 不断地重新计算和重新定位标签 table 在 tiff (IFD) 的末尾,那么这将是每个图像的 O(n^2)。
我使用此技术将科学图像传感器数据从 genicam 设备流式传输到磁盘。它允许以更高的 FPS 进行捕获。
将视觉分析与 multi-tiff(目录)结构相结合,可以在单个 tiff 中为每个帧保存多个感兴趣区域。