我正在尝试编写单个多页tiff文件,该文件是128像素x 128像素x 122000帧的16位无符号整数。 ImageJ或简短的Python脚本可以在不到一分钟的时间内在快速机器上执行此操作。在同一台机器上,使用我尝试过的任何方法,MATLAB可能需要数天才能完成。这是我到目前为止所尝试的:
使用imwrite将IMG写入test.tif(由MATLAB文档推荐)
tic
numframes=size(IMG,3);
divider=10^(floor(log10(numframes))-1);
imwrite(IMG(:,:,1),'test.tif');
for i=2:numframes;
imwrite(IMG(:,:,i),'test.tif','WriteMode','append');
if (round(i/divider)==i/divider)
fprintf('Frame %d written in %.0f seconds, %2d percent complete, time left=%.0f seconds \n', ...
i, toc, i/numframes*100, (numframes - i)/(i/toc));
end
end
导致以下输出:
帧10000写入104秒,8.196721e + 00%完成, 剩余时间= 1163秒框架20000用296秒写入, 1.639344e + 01%完成,剩余时间= 1509秒帧30000写在590秒,2.459016e + 01%完成,剩余时间= 1809 秒帧40000写在1035秒,3.278689e + 01% 完成,剩余时间= 2121秒框架50000写在1682秒, 4.098361e +完成01%,剩余时间= 2421秒
注意随着更多帧的写入,时间呈指数级增长。
直接使用Tiff类
if bigtiff
t = Tiff(fname,'w8');
else
t = Tiff(fname,'w');
end
tagstruct.ImageLength = size(image,1);
tagstruct.ImageWidth = size(image,2);
tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
if bitspersamp==16
tagstruct.BitsPerSample = 16;
end
if bitspersamp==32
tagstruct.BitsPerSample = 32;
end
tagstruct.SamplesPerPixel = 1;
tagstruct.RowsPerStrip = 256;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
tagstruct.Software = 'MATLAB';
t.setTag(tagstruct);
t.write(image(:,:,1));
numframes = size(image,3);
divider = 10^(floor(log10(numframes))-1);
tic
for i=2:numframes
t.writeDirectory();
t.setTag(tagstruct);
t.write(image(:,:,i));
if (round(i/divider)==i/divider)
fprintf('Frame %d written in %.0f seconds, %2d percent complete, time left=%.0f seconds \n', ...
i, toc, i/numframes*100, (numframes - i)/(i/toc));
end
end
t.close();
导致以下输出:
Frame 10000 written in 66 seconds, 8.196721e+00 percent complete, time left=743 seconds
Frame 20000 written in 225 seconds, 1.639344e+01 percent complete, time left=1145 seconds
Frame 30000 written in 481 seconds, 2.459016e+01 percent complete, time left=1474 seconds
Frame 40000 written in 915 seconds, 3.278689e+01 percent complete, time left=1877 seconds
Frame 50000 written in 1512 seconds, 4.098361e+01 percent complete, time left=2177 seconds
尝试使用BigTIFF库不起作用
在此讨论之后: http://blogs.mathworks.com/steve/2013/08/07/tiff-bigtiff-and-blockproc/
我尝试通过将第73行更改为:
来转换代码以使用uint16数据 obj.TiffObject.setTag('BitsPerSample', 16);
但写完后用
outFileWriter = bigTiffWriter('test.tif', inFileInfo(1).Height, inFileInfo(1).Width, tileSize(1), tileSize(2));
for i=1:122000
blockproc(IMG(:,:,i),tileSize,@(b) b.data,'Destination',outFileWriter);
if rem(i,10000)==0
fprintf('Frame %d done\n',i)
end
end
尝试回读时出现以下错误:
Unexpected Standard exception from MEX file.
What() is:std::bad_alloc
..
Error in imtifinfo (line 27)
raw_tags = tifftagsread(filename,0,0,0);
Error in imfinfo (line 183)
info = feval(fmt_s.info, filename);
Error in TiffReader (line 11)
InfoImage=imfinfo(fname);
在相关的说明中,在磁盘上预先分配正确大小的文件没有区别
我认为这是一个很小的机会,这是一个文件I / O问题,在这种情况下预先分配磁盘上的空间可能是相关的,所以我尝试了这里提到的:http://www.mathworks.co.uk/matlabcentral/newsreader/view_thread/241072,即:
% Create the file
fh = javaObject('java.io.RandomAccessFile', 'test.dat', 'rw');
% Allocate the right amount of space
fh.setLength(1024);
% Close the file
fh.close();
但没有区别。
非常感谢任何帮助。
答案 0 :(得分:1)
我也曾经遇到这个问题。 Matlab 2018b似乎有两个可以处理tiff的.mexw64文件。
wtifc.mexw64
调用的\toolbox\matlab\imagesci\private
中的 writetif.m
,由imwrite使用
和
tifflib.mexw64
,相同的位置,由Tiff对象使用。
两者都随着多图像tiff文件而变慢。使用fwrite
写入所有图像数据并以指向该数据的指针结尾要快得多。
我使用此脚本测试了三种方法,差异很大。 这是使用matlab 2018b完成的。
clear all;close all; clc; fclose all;
%generate some data
N=1E3;
IM=imread('landOcean.jpg');
IM = uint16(sum(IM,3));
IM = IM(100:310,960:1170);
IM = IM-min(IM(:));
IM=IM*(2^15/max(IM(:)));
IM = repmat(IM,[1,1,N])+randi((2^15)-1,[size(IM,1),size(IM,2),N],'uint16');
S = (numel(IM)/N*2)/2^20;
%imread writespeed
methods = {'imwrite','tifflib','fTIF'};
for M = 1:length(methods)
method = methods{M};
%file
filename = [method,'.tif'];
if exist(filename,'file'), delete(filename);end
switch method
case 'imwrite'
%timing vector
t = zeros(1,100+1);
tic;
imwrite(IM(:,:,1),filename);
t(2)=toc;
for ct = 2:100
imwrite(IM(:,:,ct),filename,'WriteMode','append');
t(ct+1)=toc;
end
case 'tifflib'
%timing vector
t = zeros(1,200+1);
tic;
tf = Tiff(filename,'w');
for ct = 1:200
if ct>1,tf.writeDirectory;end
tf.setTag('Photometric',Tiff.Photometric.MinIsBlack);
tf.setTag('Compression',Tiff.Compression.None);
tf.setTag('BitsPerSample',16);
tf.setTag('SamplesPerPixel',1);
tf.setTag('SampleFormat',Tiff.SampleFormat.UInt);
tf.setTag('ExtraSamples',Tiff.ExtraSamples.Unspecified);
tf.setTag('ImageLength',size(IM,1));
tf.setTag('ImageWidth',size(IM,2));
tf.setTag('PlanarConfiguration',Tiff.PlanarConfiguration.Chunky);
tf.setTag('ImageDescription',sprintf('ImageJ=1.51j\nchannels=%.0f',size(IM,3)));
tf.write(IM(:,:,ct));
t(ct)=toc;
end
tf.close();
case 'fTIF'
%timing vector
t = zeros(1,size(IM,3)+1);
tic
fTIF = Fast_Tiff(filename);
for ct = 1:size(IM,3)
fTIF = fTIF.WriteIMG(IM(:,:,ct)');
t(ct)=toc;
end
tic
fTIF.close;
toc
otherwise
error('unknown method')
end
S = (size(IM,1)*size(IM,2)*2)/2^20; %MB/frame
y = S./diff(t);
subplot(1,length(methods),M)
plot([1:length(y)],y);
title(sprintf('Writing with %s; mean = %.2f MB/s',method,mean(y)))
ylabel('Writing speed (MB/s)')
xlabel('Frame');
drawnow;
end
fTIF方法的代码:
答案 1 :(得分:0)
我遇到了同样的问题,但情况更糟:即使你写了另一个tiff,写一帧的时间也在增加。
所以一个解决方案(在我的情况下对多个文件更好)是每个shell命令调用restart matlab session。
所以在你的“writeTIFF.m”中,你应该有一个变量“startFrame”,并在你脚本的末尾添加一个“exit”。 您可以使用此行批量处理此类批处理(或linux / unix下的等效批处理):
@echo off
setlocal EnableDelayedExpansion
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (100,100,300) Do (
echo matlab -r "startFrame=%%G;writeTIFF" -nosplash -nodesktop -wait
matlab -r "startFrame=%%G;writeTIFF" -nosplash -nodesktop -wait
)
echo Done
我没有经过大量测试,但它应该做的是预期:重启matlab 3次,并连续初始化值为100,200和300的变量“startFrame”。