単純な 2D 画像畳み込みを実行したいのですが、カーネルのサイズが偶数です。カーネル センターにはどのインデックスを選択する必要がありますか? 答えをグーグルで検索し、既存のコードを調べてみました。人々は通常、新しい 0 の前にもう 1 つのサンプルがあるようにカーネルを中央に配置します。したがって、4x4 カーネルがある場合、中央に配置されたインデックスは-2 -1 0 +1
. あれは正しいですか?もしそうなら、それはなぜですか?なぜ-2 -1 0 +1
正しいのに正しく-1 0 +1 +2
ないのか誰か説明できますか? FFTを使用せずに畳み込みを実行したいことに注意してください。
質問する
14384 次
3 に答える
10
私があなたの質問を正しく理解していれば、サイズが均一なカーネルの場合、新しいゼロの前にもう1つのサンプルがあるようにカーネルを中央に配置するのが慣例であることは正しいです。
したがって、幅 4 のカーネルの場合、中央のインデックスは-2 -1 0 +1
上記のようになります。
ただし、これは単なる慣例です。非対称畳み込みはとにかくほとんど使用されず、非対称の正確な性質 (左/右など) は「正しい」結果とは関係ありません。ほとんどの実装がこのように動作する理由は、同じ入力が与えられた場合に同等の結果が得られるようにするためだと思います。
周波数ドメインで畳み込みを実行する場合、とにかく画像サイズに一致するようにカーネルがパディングされ、空間ドメインで畳み込みを実行していることを既に述べました。
そもそもなぜ均一なサイズのカーネルを使用する必要があるのか について、私はもっと興味をそそられます。
于 2013-06-11T06:48:26.710 に答える
1
正しい答えは、マトリックスのサイズが均等かどうかに関係なく、結果のピクセルを左上隅に返すことです。次に、単純なスキャンラインで操作を簡単に実行でき、メモリは必要ありません。
private static void applyBlur(int[] pixels, int stride) {
int v0, v1, v2, r, g, b;
int pos;
pos = 0;
try {
while (true) {
v0 = pixels[pos];
v1 = pixels[pos+1];
v2 = pixels[pos+2];
r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
g = ((v0 >> 8 ) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
b = ((v0 ) & 0xFF) + ((v1 ) & 0xFF) + ((v2 ) & 0xFF);
r/=3;
g/=3;
b/=3;
pixels[pos++] = r << 16 | g << 8 | b;
}
}
catch (ArrayIndexOutOfBoundsException e) { }
pos = 0;
try {
while (true) {
v0 = pixels[pos];
v1 = pixels[pos+stride];
v2 = pixels[pos+stride+stride];
r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
g = ((v0 >> 8 ) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
b = ((v0 ) & 0xFF) + ((v1 ) & 0xFF) + ((v2 ) & 0xFF);
r/=3;
g/=3;
b/=3;
pixels[pos++] = r << 16 | g << 8 | b;
}
}
catch (ArrayIndexOutOfBoundsException e) { }
}
于 2016-07-12T12:27:46.897 に答える