以下情况。我在4D矩阵中有一个时间序列的三维图像。 3D图像的分辨率为177 * 209 * 156。 然后我有一个3D-Mask图像,它携带3D图像中500个组中的一个体素所属的信息,因此它与一个3D图像具有相同的维度,但值为[2; 501](502实际上,但最后一组是"局外人"那些将被忽略)。 现在对于那些3D图像,我想要一个500 * X矩阵,它保存每个图像的每个组的平均值,其中X是图像计数(在这种情况下为1500)。我为生成此向量而编写的代码(对于每个图像)如下:
...
final_vec = zeros(500, TRs);
mask_hist = get_histogram(mask_mat);
mask_hist(1) = [];
mask_hist(end) = [];
for i = 1:TRs
TR = new_nifti_mat(:,:,:,i);
for k = 1:numel(TR)
if mask_mat(k) < 502 && mask_mat(k) > 1
final_vec(mask_mat(k) - 1, i) = final_vec(mask_mat(k) - 1, i) + TR(k);
end
end
final_vec(:, i) = final_vec(:, i)./mask_hist
end
...
这段代码的问题在于它永远运行。对于一组数据,它运行超过12小时。我知道matlab对于for循环是不好的,并且可能有一个非常优雅的1或2行代码的方式,只需要我的代码所需的时间的一小部分
最诚挚的问候 Uzaku
答案 0 :(得分:2)
让我们先创建示例数据:
x = rand(4,4,2,8); %// random data
mask(:,:,1) = [ 3 2 2 3
2 4 4 2
2 4 4 2
3 2 2 3 ];
mask(:,:,2) = mask(:,:,1); %// example 4x4x2 mask
accumarray
遍历每个3D图像,并且每个图像使用accumarray
按组进行平均分析:
mask = mask - min(mask(:)) + 1; %// so that lowest value is 1
result = NaN(max(mask(:)),size(x,4)); %// preallocate result
for n = 1:size(x,4);
result(:,n) = accumarray(mask(:), reshape(x(:,:,:,n),[],1), [], @mean, NaN);
end
bsxfun
和矩阵乘法;没有循环线性化前三个维度并构建一个零掩码,以便每个组中所有值的累积成为矩阵乘法:
mask2 = bsxfun(@eq, mask(:), min(mask(:)):max(mask(:))).'; %'
result = mask2*reshape(x,[],size(x,4)); %// sum for each group
result = bsxfun(@rdivide, result, sum(mask2,2)); %// transform sum into average