如何将这些图像组合在一起?
How to put these images together?
我有200
个时间点。对于每个时间点,都有一张图像,大小为40*40 double
,对应于该时间点。例如image 1
对应time point 1
; image k
对应 time point k
(k = 1,2,...,200
).
时间点为T = 1:200
,图像命名为Image_T
,因此Image_1
、Image_2
等
我想将所有这些 200
图片放在一起。最终尺寸为 40*40*200
双倍。最终图像看起来像 fMRI 图像(fmri_szX = 40
、fmri_szY = 40
和 fmri_szT = 200
)。如何实现?
谢谢!
动态变量
请注意,虽然这是 可能的 ,但它被认为是糟糕的编程(例如 here, or this blog by Loren and even the Mathworks in their documentation 告诉你不要这样做)。最好将图像直接加载到 3D 数组或单元格结构中,避免动态变量名称。为了完整起见,我只是发布了这个;如果您碰巧必须使用此解决方案,则应立即更改为 (cell-) 数组。
关于为什么 eval
是个坏主意的链接文章的要点是,MATLAB 无法再预测操作的结果。例如 A=3*(2:4)
被 MATLAB 识别为输出 double-array。如果你 eval
东西,MATLAB 就不能再这样做了。 MATLAB 是一种解释型语言,即先读取每一行代码 运行,而无需事先编译整个代码。这意味着每次 MATLAB 遇到 eval
时,它都必须停止,计算表达式,然后检查输出,存储它,然后继续。 MATLAB 使用的大多数 speed-engines(JIT/MAGMA 等)如果不预测语句的结果就无法工作,因此会在 eval
评估期间关闭,使您的代码非常慢。
eval
的使用也有安全方面的问题。考虑以下因素:
var1=1;
var2=2;
var3=3;
varnames={'var1','var2; disp(''GOTCHA''); %', 'var3'};
accumvar=[];
for k=1:numel(varnames)
vname=varnames{k};
disp(['Reading from variable named ' vname]); eval(['accumvar(end+1)=' vname ';']);
end
现在 accumvar
将包含所需的变量名称。但是如果你不设置 accumvar
作为输出,你也可以不使用 disp
,但是例如eval('rm -rf ~/*')
这会在不告诉您它正在这样做的情况下格式化您的整个磁盘。
循环方法
for ii = 200:-1:1
str = sprintf('Image_%d',ii);
A(:,:,ii) = eval(str);
end
这将创建您的矩阵。请注意,我让 for
向后循环 运行,以便以最大尺寸初始化 A
。
Semi-vectorised接近
str=strsplit(sprintf('image_%d ',1:200),' '); % Create all your names
str(end)=[]; % Delete the last entry (empty)
%Problem: eval cannot handle cells, loop anyway:
for ii = 200:-1:1
A(:,:,ii)=eval(str{ii});
end
eval
不支持数组,所以不能直接把cellarray塞进去str
.
动态文件名
尽管标题与上述类似,但这意味着您的文件名 是结构化的,所以在文件浏览器中,而不是在 MATLAB 中。我假设这里是 .jpg 文件,但您可以添加每个支持的图像扩展名。此外,请确保将 所有 图像放在一个文件夹中,并且没有带有该扩展名的其他图像,或者您必须修改 dir()
调用以仅包含所需图像。
filenames = dir('*.jpg');
for ii = length(filenames):-1:1
A(:,:,:,ii) = imread(filenames{ii});
end
图像通常被读取为 m*n*3
文件,其中 m*n
是以像素为单位的图像大小,3
源于这样一个事实,即它们被 imread
。因此 A
现在是一个 4D 矩阵,结构为 m*n*3*T
,其中最后一个索引对应图像的时间,前三个是 RGB 格式的图像。
由于您没有说明如何获得 40*40
double,因此我保留了 4D 矩阵。你可以阅读它们然后切换到使用 RGB 的 uint16
解释,这是一个单一的数字,这将导致一个 m*n*1*T
变量,你可以通过调用 A = squeeze(A(:,:,1,:));
我有200
个时间点。对于每个时间点,都有一张图像,大小为40*40 double
,对应于该时间点。例如image 1
对应time point 1
; image k
对应 time point k
(k = 1,2,...,200
).
时间点为T = 1:200
,图像命名为Image_T
,因此Image_1
、Image_2
等
我想将所有这些 200
图片放在一起。最终尺寸为 40*40*200
双倍。最终图像看起来像 fMRI 图像(fmri_szX = 40
、fmri_szY = 40
和 fmri_szT = 200
)。如何实现?
谢谢!
动态变量
请注意,虽然这是 可能的 ,但它被认为是糟糕的编程(例如 here, or this blog by Loren and even the Mathworks in their documentation 告诉你不要这样做)。最好将图像直接加载到 3D 数组或单元格结构中,避免动态变量名称。为了完整起见,我只是发布了这个;如果您碰巧必须使用此解决方案,则应立即更改为 (cell-) 数组。
关于为什么 eval
是个坏主意的链接文章的要点是,MATLAB 无法再预测操作的结果。例如 A=3*(2:4)
被 MATLAB 识别为输出 double-array。如果你 eval
东西,MATLAB 就不能再这样做了。 MATLAB 是一种解释型语言,即先读取每一行代码 运行,而无需事先编译整个代码。这意味着每次 MATLAB 遇到 eval
时,它都必须停止,计算表达式,然后检查输出,存储它,然后继续。 MATLAB 使用的大多数 speed-engines(JIT/MAGMA 等)如果不预测语句的结果就无法工作,因此会在 eval
评估期间关闭,使您的代码非常慢。
eval
的使用也有安全方面的问题。考虑以下因素:
var1=1;
var2=2;
var3=3;
varnames={'var1','var2; disp(''GOTCHA''); %', 'var3'};
accumvar=[];
for k=1:numel(varnames)
vname=varnames{k};
disp(['Reading from variable named ' vname]); eval(['accumvar(end+1)=' vname ';']);
end
现在 accumvar
将包含所需的变量名称。但是如果你不设置 accumvar
作为输出,你也可以不使用 disp
,但是例如eval('rm -rf ~/*')
这会在不告诉您它正在这样做的情况下格式化您的整个磁盘。
循环方法
for ii = 200:-1:1
str = sprintf('Image_%d',ii);
A(:,:,ii) = eval(str);
end
这将创建您的矩阵。请注意,我让 for
向后循环 运行,以便以最大尺寸初始化 A
。
Semi-vectorised接近
str=strsplit(sprintf('image_%d ',1:200),' '); % Create all your names
str(end)=[]; % Delete the last entry (empty)
%Problem: eval cannot handle cells, loop anyway:
for ii = 200:-1:1
A(:,:,ii)=eval(str{ii});
end
eval
不支持数组,所以不能直接把cellarray塞进去str
.
动态文件名
尽管标题与上述类似,但这意味着您的文件名 是结构化的,所以在文件浏览器中,而不是在 MATLAB 中。我假设这里是 .jpg 文件,但您可以添加每个支持的图像扩展名。此外,请确保将 所有 图像放在一个文件夹中,并且没有带有该扩展名的其他图像,或者您必须修改 dir()
调用以仅包含所需图像。
filenames = dir('*.jpg');
for ii = length(filenames):-1:1
A(:,:,:,ii) = imread(filenames{ii});
end
图像通常被读取为 m*n*3
文件,其中 m*n
是以像素为单位的图像大小,3
源于这样一个事实,即它们被 imread
。因此 A
现在是一个 4D 矩阵,结构为 m*n*3*T
,其中最后一个索引对应图像的时间,前三个是 RGB 格式的图像。
由于您没有说明如何获得 40*40
double,因此我保留了 4D 矩阵。你可以阅读它们然后切换到使用 RGB 的 uint16
解释,这是一个单一的数字,这将导致一个 m*n*1*T
变量,你可以通过调用 A = squeeze(A(:,:,1,:));