匹配三维数组中矩阵的值

时间:2017-08-23 10:09:10

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

我正在尝试匹配图像中的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值与RGB [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

更快的解决方案是什么?

3 个答案:

答案 0 :(得分:5)

我们可以将每个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.

答案 1 :(得分:3)

您可以按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')可以以矢量化方式应用。然后根据需要重新获得所获得的结果。

答案 2 :(得分:0)

你可以循环遍历颜色,这比循环每个像素要快得多。

% 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