4

我試圖匹配圖像中的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 

什麼是更快的解決方案?

回答

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

好主意,並且速度很快! –

+0

感謝您的回答。您能否詳細說明「降維」是如何工作的? – Likeunknown

+0

@Likeunknown在帖子開頭添加了幾條評論。檢查出來! – Divakar

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 
+0

感謝您的回答。它是否提供了所需的匹配矩陣?對不起,我無法理解 – Likeunknown

+0

每個「匹配」矩陣都是圖像的大小,對於匹配「RGBset」矩陣的行「ii」中的顏色的像素,爲「true」。路易斯的回答可能會更快 – Wolfie

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')可以以矢量化的方式應用。然後根據需要重新獲得所得結果。