如何使用逻辑索引MATLAB获得3d矩阵中每个切片中特定区域的平均值

如何使用逻辑索引MATLAB获得3d矩阵中每个切片中特定区域的平均值,matlab,matrix,vectorization,Matlab,Matrix,Vectorization,在Matlab中 如果我有如下的3d矩阵,我想知道每个切片中值大于5的区域的平均值。我如何使用逻辑索引来实现这一点,请不要使用循环 我想以一个3乘1的数组结束,每个元素表示相应切片中区域的平均值 m3d=randi(10[3,3,3]) m3d(:,:,1)= m3d(:,:,2)= m3d(:,:,3)= 获取索引 3d_index = m3d > 5; 我的期末考试 result = mean(m3d(3d_index)); 我不希望所有区域的平均值都是一种方法- %// 3d m

在Matlab中

如果我有如下的3d矩阵,我想知道每个切片中值大于5的区域的平均值。我如何使用逻辑索引来实现这一点,请不要使用循环

我想以一个3乘1的数组结束,每个元素表示相应切片中区域的平均值

m3d=randi(10[3,3,3])

m3d(:,:,1)=

m3d(:,:,2)=

m3d(:,:,3)=

获取索引

3d_index = m3d > 5;
我的期末考试

result = mean(m3d(3d_index));
我不希望所有区域的平均值都是一种方法-

%// 3d mask of elements greater than 5
mask = m3d>5

%// Sum of all elements greater than 5 in each slice
sumvals = sum(reshape(m3d.*mask,[],size(m3d,3)))

%// Count of elements great than 5 in each slice
counts = sum(reshape(mask,[],size(m3d,3)))

%// Final output of mean values for the regions with >5 only
out = sumvals./counts
标杆管理 下面是一些运行时测试,以查看所有发布的方法的位置。对于测试,我们随机选取了一个大小为1500 x 1500 x 100的3D数组,其值在区间
[1255]
内。下面列出了基准测试代码-

m3d = randi(255,1500,1500,100); %// Input 3D array

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp('------------------------ With SUMMING and COUNTING ')
tic
%// .... Proposed approach in this solution
toc, clear out counts sumvals mask

disp('------------------------ With FOR-LOOP ')
tic
N   = size(m3d, 3);
out = zeros(N, 1);
for k = 1:size(m3d,3)
        val    = m3d(:,:,k);
        lix    = val>5;
        out(k) = mean(val(lix));
end;
toc, clear out lix val k N

disp('----------------------- With ACCUMARRAY')
tic
ind = m3d>5;
result = accumarray(ceil(find(ind)/size(m3d,1)/size(m3d,2)), m3d(ind), [], @mean);
toc, clear ind result

disp('----------------------- With NANMEAN')
tic
m3d(m3d<5) = NaN; %// Please note: This is a bad practice to change input
out = nanmean(nanmean(m3d,1),2);
toc

您可以使用掩码数组来执行此操作,如下所示:

m3d = randi(10,[3,3,3]);

%Set values less than 5 to NaN
m3d(m3d<5) = NaN
nanmean(nanmean(m3d,1),2)
m3d=randi(10[3,3,3]);
%将小于5的值设置为NaN

m3d(m3d这可以通过以下方式轻松完成:


为什么要避免循环?对于你的问题来说,循环可能非常方便,而且速度也很快。嗨,CST Link 44,我必须把它放在一个while循环中,我说的是256*256*100矩阵。所以我尽量避免循环。我认为Divakar有一个很好的解决方案。感谢使用
nanmean
的好主意!
nanmean
是一个很好的函数ion to know:)您还可以使用
挤压
使其类似于OP所需的输出。另外,您可能不会在
nanmean
中使用
1
2
而不是
nanmean,因为它们是默认值。说到这里,你不能使用嵌套的
nanmean
,因为它会误导人。您可以手动测试它们以了解它。或者您可以尝试将其作为一个整体用于单个切片。只有当所有列都具有相同数量的非NaN值时,它才会给出正确的结果。次要说明:
nanmean
需要stats工具箱。如果您想实现自己版本的
nanmean
,只需计算每行/列或维度中有多少
NaN
s,将
NaN
值设置为零,然后要进行平均,只需从维度中的元素总数中减去该数字即可。只是为了澄清。。所有的解决方案给你的结果都一样吗?@SanthanSalai不,我没有检查,如果有兴趣,我会把值正确性部分留给OP检查。
%// 3d mask of elements greater than 5
mask = m3d>5

%// Sum of all elements greater than 5 in each slice
sumvals = sum(reshape(m3d.*mask,[],size(m3d,3)))

%// Count of elements great than 5 in each slice
counts = sum(reshape(mask,[],size(m3d,3)))

%// Final output of mean values for the regions with >5 only
out = sumvals./counts
m3d = randi(255,1500,1500,100); %// Input 3D array

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp('------------------------ With SUMMING and COUNTING ')
tic
%// .... Proposed approach in this solution
toc, clear out counts sumvals mask

disp('------------------------ With FOR-LOOP ')
tic
N   = size(m3d, 3);
out = zeros(N, 1);
for k = 1:size(m3d,3)
        val    = m3d(:,:,k);
        lix    = val>5;
        out(k) = mean(val(lix));
end;
toc, clear out lix val k N

disp('----------------------- With ACCUMARRAY')
tic
ind = m3d>5;
result = accumarray(ceil(find(ind)/size(m3d,1)/size(m3d,2)), m3d(ind), [], @mean);
toc, clear ind result

disp('----------------------- With NANMEAN')
tic
m3d(m3d<5) = NaN; %// Please note: This is a bad practice to change input
out = nanmean(nanmean(m3d,1),2);
toc
------------------------ With SUMMING and COUNTING 
Elapsed time is 0.904139 seconds.
------------------------ With FOR-LOOP 
Elapsed time is 2.321151 seconds.
----------------------- With ACCUMARRAY
Elapsed time is 4.350005 seconds.
----------------------- With NANMEAN
Elapsed time is 1.827613 seconds.
m3d = randi(10,[3,3,3]);

%Set values less than 5 to NaN
m3d(m3d<5) = NaN
nanmean(nanmean(m3d,1),2)
ind = m3d>5;
result = accumarray(ceil(find(ind)/size(m3d,1)/size(m3d,2)), m3d(ind), [], @mean);