私は現在、オクターブのエッジ検出器で作業しています。 JavaやPythonのような他のプログラミング言語から来ているので、私はforループを反復するのに慣れています。今オクターブでは、これは重大なパフォーマンスのヒットを引き起こし、私は自分のコードをベクトル化する方法を理解するのに少し難しいです。私は、次の2つのコード片を有する:サブマトリクス(およびサブベクトル)の演算をベクトル化できますか?
1)
function zc = ZeroCrossings(img, T=0.9257)
zc = zeros(size(img));
# Iterate over central positions of all 3x3 submatrices
for y = 2:rows(img) - 1
for x = 2:columns(img) - 1
ndiff = 0;
# Check all necessary pairs of elements of the submatrix (W/E, N/S, NW/SE, NE/SW)
for d = [1, 0; 0, 1; 1, 1; 1, -1]'
p1 = img(y-d(2), x-d(1));
p2 = img(y+d(2), x+d(1));
if sign(p1) != sign(p2) && abs(p1 - p2) >= T
ndiff++;
end
end
# If at least two pairs fit the requirements, these coordinates are a zero crossing
if ndiff >= 2
zc(y, x) = 1;
end
end
end
end
2)
function g = LinkGaps(img, k=5)
g = zeros(size(img));
for i = 1:rows(img)
g(i, :) = link(img(i, :), k);
end
end
function row = link(row, k)
# Find first 1
i = 1;
while i <= length(row) && row(i) == 0
i++;
end
# Iterate over gaps
while true
# Determine gap start
while i <= length(row) && row(i) == 1
i++;
end
start = i;
# Determine gap stop
while i <= length(row) && row(i) == 0
i++;
end
# If stop wasn't reached, exit loop
if i > length(row)
break
end
# If gap is short enough, fill it with 1s
if i - start <= k
row(start:i-1) = 1;
end
end
end
これらの機能の両方の第2のケースで部分行列(又は行と下位行を繰り返し処理する)、及び特に最初のプログラムは私のプログラムをかなり遅くしているようです。
この関数は、ゼロ交差(その対応する3×3近傍特定の要件に合う画素)が見出された1Sと、画素(
img
)のマトリックスを受け取り、バイナリ(0/1)行列を返します。ループの外側2は、何とかベクトル化できるように見えます。私は体をそれ自身の関数に入れることができます(引数として必要な部分行列を取る)が、すべての部分行列でこの関数を呼び出す方法を理解できず、対応する(中心の)位置を戻り値に設定します。
内側のforループもベクトル化できる場合のボーナスポイントです。
この関数は、前の出力からバイナリ行列を取り込み、その行のギャップを埋めます(つまり、1に設定します)。ギャップは、長さ< = kの一連の0として定義され、両辺は1で境界付けられます。
今や、少なくとも外側のループ(
LinkGaps
のもの)はベクトル化可能です。しかし、link
のwhile
ループは再び単一の要素ではなくサブベクトルで動作するので、どのようにベクトル化するのかはわかりません。
タスク1は、ゼロ交差を検出するように設計されたカーネルを使用して畳み込みを解くことができます。 – Suever