2017-02-09 6 views
2

したがって、いくつかのforループを1つの行にベクトル化する必要があります。私は1つと2つのfor-loopをベクトル化する方法を理解していますが、それ以上のことをするのは本当に苦労しています。本質的に、私はS =サイズ(M)サイズn×m個の元の行列Mのサイズの "ぼけ" マトリクスM2(N-2)×(M-2)を計算しています:Matlab:4つのループのネストされたベクトル化

for x = 0:1 
    for y = 0:1 
     m = zeros(1, 9); 
     k = 1; 
     for i = 1:(s(1) - 1) 
      for j = 1:(s(2) - 1) 
       m(1, k) = M(i+x,j+y); 
       k = k+1; 
      end 
     end 
    M2(x+1,y+1) = mean(m); 
    end 
end 

これは私が得ている最も近い:私は2つの変数(x、y)を割り当てる「通信」のいくつかの種類が存在しなければならないよう

for x=0:1 
    for y=0:1 
     M2(x+1, y+1) = mean(mean(M((x+1):(3+x),(y+1):(3+y)))) 
    end 
end 

を1行のソリューションにどの近づくためには、それがインデックスに思えますM2以上および index over M;私はそれが他の方法でどうやってできるのか分かりませんが、解決策があると確信しています。

答えて

3

MATLABの畳み込み関数を使用してこれを行う理由がありますか?オーバーラップする近隣を持つ3 x 3平均カーネルでぼかしを実行しています。これはまさに畳み込みがやっていることです。あなたはconv2を使用して、これを実行することができます。

M2 = conv2(M, ones(3)/9, 'valid'); 

'valid'フラグはあなたが要求したとして、あなたが両方の次元でsize(M) - 2行列を返すことを保証します。


コードでは、これを4 x 4マトリックス用にハードコードしています。

rng(123); 
M = rand(4, 4); 
s = size(M); 

私たちはあなたのコードでこれを実行すると、我々が得る:

>> M2 

M2 = 

    0.5054 0.4707 
    0.5130 0.5276 

はでこれをやって、我々は正しい結果を持っているかどうかを確認するためにダブルチェックのは、ランダムな4×4行列を生成するようにするにはconv2:しかし

>> M2 = conv2(M, ones(3)/9, 'valid') 

M2 = 

    0.5054 0.4707 
    0.5130 0.5276 

、あなたは第一原理からこれを実行したい場合は、ピクセルの重なりがいななきループを使って逃げ出すことは非常に困難です。あなたが持っている2つのループアプローチは十分であり、問​​題に適切に取り組んでいます。私はハードコードされているのではなく、入力のサイズを作ります。

function M2 = blur_fp(M) 
s = size(M); 
M2 = zeros(s(1) - 2, s(2) - 2); 
for ii = 2 : s(1) - 1 
    for jj = 2 : s(2) - 1 
     p = M(ii - 1 : ii + 1, jj - 1 : jj + 1); 
     M2(ii - 1, jj - 1) = mean(p(:)); 
    end 
end 

コードの最初の行は、我々はblur_fpを呼び出す関数を定義しています。したがって、このような何かを行う関数を記述します。次のコード行は、入力行列のサイズを決定するとともに、出力を格納するための空白行列を初期化します。次に、カーネルがイメージの境界の外に出ることなく可能な行列内の各ピクセル位置をループし、各ピクセル位置を中心とする3×3近傍を取得し、次にを展開する行列を単一列のベクトル、平均を求め、適切な出力に格納します。小さなカーネルと比較的大きな行列の場合、これはOKを実行するはずです。


あなたが重なり合う地域を取り、列にそれらをアンロールユーザー Divakarim2col_sliding機能を使用することができ、このもう少しかかります。したがって、各列は近傍を表し、ベクトル - 行列乗算を使用して入力をブラーすることができます。その後、マトリックスに戻って結果を再構築するために reshapeを使用します。

T = im2col_sliding(M, [3 3]); 
V = ones(1, 9)/9; 
s = size(M); 
M2 = reshape(V * T, s(1) - 2, s(2) - 2); 

これは残念ながら、単一のラインで行うことができないあなたは組み込み関数を使用しない限り。私はあなたの意図が何であるか分かりませんが、あなたがここで見たアプローチの範囲は、これを効率的に行う方法についていくつかの洞察を与えました。 BTWでは、小さな行列(すなわち、4×4)のループを使用する方が効率が良い場合があります。入力のサイズを大きくするとパフォーマンスの変化に気付き始めます.JITが大幅に改善されたとき、R2015bのようにループを使用することは競争力があると私は主張します。

+0

ありがとうございます!運動の目的は、「第一原理」だけを使ってこれを行うことだったと思います。あなたが話しているこれらの機能を知らないと仮定します。しかし、すべてとすべて、私はこれがmatlabの私の実際の知識のために役立つと思う。 –

+0

@DylanBrown OK、その場合、2つの 'for'ループで何を持っているかは、最初の原則にとって十分です。あなたはもう助けが必要ですか?そうでなければ、あなたが私の答えを受け入れることができるなら、私はそれを愛するでしょう。これは、あなたがもはや助けを必要としていないことをコミュニティに知らせます。がんばろう! – rayryeng

+0

@DylanBrown入力サイズをハードコードしないで2つの 'for'ループを使うように私の投稿を編集します。私はそれを動的にするでしょう。 – rayryeng

関連する問題