2010-06-01 66 views
6

我經常發現自己希望使用自定義函數在一個維度上摺疊n維矩陣,並且無法弄清楚是否有可用於執行此操作的簡明咒語。在MATLAB中通過數組的單個維度分配函數?

例如,在解析圖像時,我經常想要做這樣的事情。 (注說明性的例子只有我知道這個特定的情況下約rgb2gray!。)

img = imread('whatever.jpg'); 
s = size(img); 
for i=1:s(1) 
    for j=1:s(2) 
    bw_img(i,j) = mean(img(i,j,:)); 
    end 
end 

我很想表達這種類似:

bw = on(color, 3, @mean); 

bw(:,:,1) = mean(color); 

是有一個簡短的方法來做到這一點?


編輯:顯然 mean已經這樣做;我希望能夠爲我寫的任何功能做到這一點。例如,

... 
    filtered_img(i,j) = reddish_tint(img(i,j,:)); 
... 

其中

function out = reddish_tint(in) 
    out = in(1) * 0.5 + in(2) * 0.25 + in(3) * 0.25; 
end 

回答

6

許多基本的MATLAB功能,如MEANMAXMINSUM等,旨在跨越特定維操作:

bw = mean(img,3); %# Mean across dimension 3 

您還可以利用這樣一個事實,即MATLAB arithmetic operators被設計爲以元素爲單位進行操作,明智的時尚在矩陣上。例如,在你的函數reddish_tint操作可以應用到圖像的所有像素與此單行:

filtered_img = 0.5.*img(:,:,1)+0.25.*img(:,:,2)+0.25.*img(:,:,3); 

到您想要的功能應用到N的任意維度處理更一般的情況下, - 維矩陣,你可能想編寫你的函數,以便它接受一個額外的輸入參數,以便操作其中的維(像上面提到的MATLAB函數那樣),然後使用一些簡單的邏輯(即if-else語句)和以元素爲單位的矩陣運算將其計算應用於矩陣的適當維度。

雖然我不會建議使用它,但是一個快速而骯髒的解決方案,但它相當難看,而且在計算上更昂貴。您可以使用該功能NUM2CELL收集沿着你的陣列的尺寸值到單元陣列的細胞,然後使用功能CELLFUN適用你的函數每個單元:

cellArray = num2cell(img,3); %# Collect values in dimension 3 into cells 
filtered_img = cellfun(@reddish_tint,cellArray); %# Apply function to each cell 
+0

mm,對這些情況很有用。我應該更清楚 - 我經常嘗試使用我寫的一些函數,比如'0.3 * r + 0.2 * g + 0.5 * b'。 – 2010-06-01 15:13:06

+0

@Alex:我更新了答案,指出如何使用元素明確的運算符將函數應用於矩陣。 – gnovice 2010-06-01 15:32:18

+0

您不需要將其轉換爲單元格數組。只需使用'arrayfun'請參閱:http://www.mathworks.com/access/helpdesk/help/techdoc/ref/arrayfun.html – Geoff 2010-06-01 16:09:26

1

好吧,如果你只關心乘以向量在一起,你可以使用點產品,像這樣:

bw(:,:,1)*[0.3;0.2;0.5] 

注意你的向量形狀符合。

2

如果你一直試圖功能適用於3維圖像中的塊由一個載體,我建議使用一對重塑,例如:

Img = rand(480,640,3); 

sz = size(Img); 
output = reshape(myFavoriteFunction(reshape(Img,[prod(sz(1:2)),sz(3)])'),sz); 

這樣你可以在換任何在矩陣的第一維上運行的函數。

編輯。 如果您輸入的圖像只有一個圖層,上面的代碼會崩潰:下面的函數可以修復它。

function o = nLayerImage2MatrixOfPixels(i) 
%function o = nLayerImage2MatrixOfPixels(i) 
s = size(i); 
if(length(s) == 2) 
    s3 = 1; 
else 
    s3 = s(3); 
end 
o = reshape(i,[s(1)*s(2),s(3)])'; 
3

您至少可以在某些任務中使用BSXFUN。它通過擴展1維尺寸以匹配另一個陣列中的尺寸來執行兩個陣列之間的按元素操作。在「偏紅色調」功能將變得

reddish_image = bsxfun(@times,img,cat(3,0.5,0.25,0.25)); 
filtered_img = sum(reddish_image,3); 

所有上述語句需要爲了工作是,img第三維具有其它尺寸的大小1或3號和尺寸可以自由地選擇。

+0

我想我可以用bsxfun拼湊一些東西...... – 2010-06-01 19:59:41

5

我寫了一個名爲'vecfun'的幫助函數,可能對此有用,如果它是你想要實現的?

link