在一系列3D图像中按组平均

时间:2015-07-18 11:50:56

标签: arrays matlab multidimensional-array 3d

以下情况。我在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

1 个答案:

答案 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

方法1:一个循环和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

方法2: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