【问题标题】:Matching values from a matrix in a 3-D array匹配 3-D 数组中矩阵的值
【发布时间】:2018-01-31 20:52:05
【问题描述】:

我正在尝试匹配图像中的 RGB 值。

         % R  G   B
RGBset = [ 3  9  12;
           4  8  13;
          11 13  13;
           8  3   2]

img(:,:,1) = [1   2   3
              6   5   4
              7   9   8
             10  11  12];

img(:,:,2) = [3  4  8;
              6  7  8;
             11 10  9;
             12 13 14];

img(:,:,3)= [3  7  2;
             4  9 10;
             5 11 12;
             6 13 14]

在这张图片中,只有一个 RGB 值与 RGBset 匹配,即[11,13,13],因此预期输出为:

[0  0  0;
 0  0  0;
 0  0  0;
 0  1  0]; % reshape(img(4,2,:),1,3) = [11, 13 13] is available in RGBset
           % no other RGB value is present in the image

我已经编写了这段代码,但是对于较大的图像它非常慢。

matched= zeros(img(:,:,1));
for r=1:size(img(:,:,1),1)
    for c=1:size(img(:,:,2),2)
     matched(r,c)=ismember(reshape(img(r,c,:),1,3),RGBset,'rows');
    end
end

更快的解决方案是什么?

【问题讨论】:

    标签: matlab image-processing matrix multidimensional-array vectorization


    【解决方案1】:

    我们可以将每个 RGB 三元组简化为一个标量,我们将为 RGBsetimg 执行此操作。这会将它们分别减少到 2D1D 矩阵。我们称之为降维。通过这些减少的数据,我们实现了内存效率,并有望提升性能。

    因此,包含这些基础的解决方案看起来像这样 -

    % Scaling array for dim reduction
    s = [256^2, 256, 1].';
    
    % Reduce dims for RGBset and img
    RGBset1D = RGBset*s;
    img1D = reshape(img,[],3)*s;
    
    % Finally use find membership and reshape to 2D
    out = reshape(ismember(img1D, RGBset1D), size(img,1), []);
    

    矢量化解决方案的基准测试

    基准代码 -

             % R  G   B
    RGBset = [ 3  9  12;
               4  8  13;
              11 13  13;
               8  3   2]
    
    % Setup inputs
    img = randi(255, 2000, 2000, 3);
    img(3,2,:) = RGBset(4,:);
    
    % Luis's soln
    disp('--------------------- Reshape + Permute ------------------')
    tic
    img2 = reshape(permute(img, [3 1 2]), 3, []).';
    matched = ismember(img2, RGBset, 'rows');
    matched = reshape(matched, size(img,1), []);
    toc
    
    % Proposed in this post
    disp('--------------------- Dim reduction ------------------')
    tic
    s = [256^2, 256, 1].';
    RGBset1D = RGBset*s;
    img1D = reshape(img,[],3)*s;
    out = reshape(ismember(img1D, RGBset1D), size(img,1), []);
    toc
    

    基准测试输出 -

    --------------------- Reshape + Permute ------------------
    Elapsed time is 3.101870 seconds.
    --------------------- Dim reduction ------------------
    Elapsed time is 0.031589 seconds.
    

    【讨论】:

    • 好主意,速度快!
    • 感谢您的回答。您能否详细说明dimension-reduction 是如何工作的?
    • @Likeunknown 在帖子开头添加了几个 cmets。看看这些!
    【解决方案2】:

    您可以将循环替换为permutereshape

    img2 = reshape(permute(img, [3 1 2]), 3, []).';
    matched = ismember(img2, RGBset, 'rows');
    matched = reshape(matched, size(img,1), []);
    

    这将创建一个 3 列矩阵 img2,其中每一行对应于来自 img 的一个像素。这样ismember(..., 'rows') 可以以矢量化方式应用。然后根据需要对获得的结果进行整形。

    【讨论】:

      【解决方案3】:

      您可以只循环颜色,这比循环每个像素要快得多。

      % Set up your colours into the 3rd dimension, so they match along the same axis
      RGB3D = reshape(RGBset,[],1,3);
      % Loop over them
      for ii = 1:size(RGB3D, 1)
          % See if all 3 members of the colour match any pixel
          matched = all(ismember(img, RGB3D(ii,:,:)),3)
          if any(matched)
              disp(matched) 
              disp(['matched color: ' num2str(ii)]); 
              % do something else with the matched pixels
          end
      end
      

      【讨论】:

      • 感谢您的回答。它是否提供所需的matched 矩阵?对不起,我无法理解
      • 每个matched 矩阵是图像的大小,true 表示与RGBset 矩阵的ii 行中的颜色匹配的像素。路易斯的回答可能更快
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 2019-09-27
      • 2020-08-31
      • 2015-07-18
      相关资源
      最近更新 更多