【问题标题】:Optimal way to find max value and indices for all indices in cell of matrices查找矩阵单元格中所有索引的最大值和索引的最佳方法
【发布时间】:2018-06-12 18:38:13
【问题描述】:

我有 100 个图像,每个图像大小为 512 x 512,存储在一个元胞数组中。

我想通过搜索所有图像来找到每个像素位置的最大值和索引。

这是示例表示:

我的代码:

imgs = cell(1,5);
imgs{1} = [2,3,2;3,2,2;3,1,1];
imgs{2} = [2,3,1;4,2,3;2,2,1];
imgs{3} = [3,2,1;5,3,5;3,2,3];
imgs{4} = [4,4,2;5,3,4;4,2,2];
imgs{5} = [4,5,2;4,2,5;3,3,1];

[nrows, ncols] = size(imgs{1});
maxVal_Mat = zeros(nrows,ncols);
maxIdx_Mat = zeros(nrows,ncols);
for nrow = 1:nrows
    for ncol = 1:ncols
        [maxVal_Mat(nrow, ncol), maxIdx_Mat(nrow, ncol)] = max(cellfun(@(x) x(nrow, ncol) , imgs));
    end
end

maxVal_Mat =

     4     5     2
     5     3     5
     4     3     3

maxIdx_Mat =

     4     5     1
     3     3     3
     4     5     3

关于如何优化此代码以节省执行时间和内存的任何想法。

注意:这是问题的示例演示,原始单元格和矩阵都很大。

谢谢,

戈皮

【问题讨论】:

  • 您对一个非常清晰的问题表示赞同!继续加油!
  • @Dev-iL 谢谢!

标签: matlab matrix


【解决方案1】:

由于所有图像的大小都相同,因此将它们存储在 3D 矩阵中比存储在元胞数组中更有意义,这也大大简化了对它们执行此类操作。您可以将imgs 从元胞数组转换为 3D 矩阵,并像这样找到最大值和索引:

imgs = cat(3, imgs{:});  % Concatenate into a 3D matrix
[maxValue, index] = max(imgs, [], 3)  % Find max across third dimension

maxValue =

     4     5     2
     5     3     5
     4     3     3

index =

     4     5     1
     3     3     3
     4     5     3

有一些关于使用元胞数组与多维数组in this post 的讨论。通常,多维数组将为您提供更好的许多操作性能,但需要连续的内存空间来存储(这可能会导致您更快地达到内存限制以增加数组大小)。元胞数组不需要连续的内存空间,因此内存效率更高,但会使某些操作复杂化。

【讨论】:

  • 谢谢,效果很好。对于我的案例,3D 矩阵和单元格使用之间的执行时间和内存使用有什么区别?
  • 好的,在这种情况下,我可以使用它来避免内存限制并仍然使用单元格对吗? [maxValue, index] = max(cat(3, adj_Imgs{slice_XIdxs}), [], 3);.
  • @Gopi:在这种情况下,仍然可以制作数据的中间副本。您最好的选择可能是仅使用 3D 数组而不是元胞数组来存储数据。对于 100 个 512×512 双精度图像,它将使用 200MB 的存储空间。这并不多(您可以查看memory 了解您的限制是多少)。
  • 将图像存储为 3D 数组对于此特定任务来说很方便,但(我认为)通常不是最佳的。正如discussed before with OP,许多图像处理管道需要将图像复制进出 3D 堆栈,因为它们不能就地应用于切片。我不认为@obchardon 的循环比这更昂贵,如果需要首先构建 3D 阵列,肯定更便宜。 (平@Gopi)
【解决方案2】:

我提出了另一种可能的解决方案:

  • 增加执行时间
  • 消耗更少的内存

如果您的图像很大并且由于内存限制您无法连接所有图像,这是一个选项。

我没有将所有图像加载到单个 3D 矩阵中,而是成对比较图像。

如果我以你为例:

imgs = cell(1,5);
imgs{1} = [2,3,2;3,2,2;3,1,1];
imgs{2} = [2,3,1;4,2,3;2,2,1];
imgs{3} = [3,2,1;5,3,5;3,2,3];
imgs{4} = [4,4,2;5,3,4;4,2,2];
imgs{5} = [4,5,2;4,2,5;3,3,1];

% Only for the first image
Mmax = imgs{1};
Mind = ones(size(imgs{1}));

for ii = 2:numel(imgs)
    % 2 by 2 comparison
    [Mmax,ind] = max(cat(3,Mmax,imgs{ii}),[],3);
    Mind(ind == 2) = ii;
end

结果:

Mmax =

   4   5   2
   5   3   5
   4   3   3

Mind =

   4   5   1
   3   3   3
   4   5   3

具体来说,相同的代码如下所示:

% your list of images
file = {'a.img','b.img','c.img'}

I = imread(file{1}); 
Mmax = I;
Mind = ones(size(I));

for ii = 2:numel(file)
    I = imread(file{ii})
    [Mmax,ind] = max(cat(3,Mmax,I),[],3);
    Mind(ind == 2) = ii;
end

【讨论】:

  • 我认为这是更好的方法。您可以通过将初始化移出循环并从 2 循环到 numel 来改进代码的第一位(我避免使用 length,也不需要假设一维元胞数组)。
  • @CrisLuengo 感谢您的输入,我已经编辑了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 2018-05-11
相关资源
最近更新 更多