MATLAB:不使用循环提取矩阵的多个部分

8

我有一个巨大的二维矩阵,想要从中提取15个不同的100x100部分。我有两个向量x和y,其中保存了部分的左上角索引。我已经使用了以下代码:

result = cam1(x(1:end):(x(1:end)+99), y(1:end):(y(1:end)+99));

但结果只是一个100x100的矩阵,而不是15x100x100的矩阵。为什么?
我知道这可以很容易地使用循环完成,但我们不允许使用循环(这是图像处理练习的一部分)。另一种可能性是编写所有15行代码,但那样有点丑陋。
你有什么优雅的解决方案吗?谢谢。
3个回答

6
有许多不需要循环即可完成的方法。大多数解决方案涉及将向量xy扩展为更大的索引矩阵,并可能使用一个或多个函数REPMATBSXFUNSUB2IND。有关矩阵索引的良好教程可以在此处找到。
但是,既然您要求一种“优雅”的解决方案,这里有一种有些不寻常的方法。它使用匿名函数以及函数ARRAYFUNCAT
indexFcn = @(r,c) cam1(r:(r+99),c:(c+99));
result = arrayfun(indexFcn,x,y,'UniformOutput',false);
result = cat(3,result{:});

解释:

第一行创建了一个匿名函数。这是一个简单的一行函数,可以即时创建而不必将其放在m文件中。该函数定义了两个输入rc,用于从cam1中提取一个100x100的子矩阵。变量indexFcn存储了一个函数句柄,用于调用该函数。请注意,匿名函数使用的cam1的值是静态的。即使变量cam1中的值发生了改变,匿名函数仍然使用创建函数时cam1中的值。

第二行调用ARRAYFUN,它将一个函数应用于数组中的每个元素。ARRAYFUN循环遍历xy中的每个条目,并将值传递给indexFcn。输出存储在result中,其中包含15个元素的单元格数组,每个单元格包含一个100x100的矩阵。

第三行使用CAT函数将100x100矩阵连接成一个100x100x15矩阵。


1
在发布问题后,我进行了更多的研究,并找到了arrayfun函数,然后我得出了以下结论: digval1 = arrayfun(@(i) sum(sum(cam1(y(i):(y(i)+99), x(i):(x(i)+99)))) / 10000, 1:15); 这已经包括了我必须执行的下一步:对部分进行平均值计算。非常感谢您的帮助,我现在知道我做了正确的事情,并且使用了您的代码来获得更美观的行: digval1 = arrayfun(@(i, j) sum(sum(cam1(j:j+99, i:i+99))) / 10000, x, y); - user112025
很高兴能帮忙!FYI:如果您可以访问图像处理工具箱,那么有一个名为MEAN2的函数(http://www.mathworks.com/access/helpdesk/help/toolbox/images/mean2.html)可以简化您的函数:digval1 = arrayfun(@(i,j) mean2(cam1(j:j+99,i:i+99)),x,y); 或者,您可以编写自己的MEAN2函数:mean2 = @(A) mean(A(:)); - gnovice

4

由于这显然是一道作业题,我不会给你完整的答案。

有几种方法可以索引矩阵。当你有一个像这样散乱的索引集时,你需要使用单个索引。因此,如果

A = rand(5,6)
A =
      0.81472      0.09754      0.15761      0.14189      0.65574      0.75774
      0.90579       0.2785      0.97059      0.42176     0.035712      0.74313
      0.12699      0.54688      0.95717      0.91574      0.84913      0.39223
      0.91338      0.95751      0.48538      0.79221      0.93399      0.65548
      0.63236      0.96489      0.80028      0.95949      0.67874      0.17119

A(3:4,3:4)

将会从A中产生一个2x2的子矩阵。但是我们也可以找到该子矩阵,如下所示:

reshape(A([13 14 18 19]),[2 2])
ans =
      0.95717      0.91574
      0.48538      0.79221

我为什么选择这个索引集?要得到答案,您需要阅读关于sub2ind的内容。
[I,J] = ndgrid(3:4,3:4);
sub2ind([5 6],I(:),J(:))
ans =
    13
    14
    18
    19

最终,看起来您想要从提取的零件中得到一个15x100x100的数组。因此,请根据我展示的部分构建必要的索引数组。最后需要进行一次重塑以使其成为正确的形状。
这应该为您完成作业提供了足够的开端。

0

你觉得所有的都太难了,试试这个:mat2cell


1
“mat2cell”函数是否适用于子矩阵在大矩阵中不均匀分布的情况?原始问题说明提供了子矩阵左上角(x,y)索引作为输入参数,因此子矩阵很可能不是均匀分布的。即它不仅仅是将大矩阵均匀分解的过程。 - cjh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接