Свертка изображения c четным ядром
Я хочу выполнить простую свертку 2D-изображения, но мое ядро имеет четный размер. Какие индексы я должен выбрать для своего центра ядра? Я попытался найти ответ в гугле и посмотреть существующие коды. Люди обычно центрируют свое ядро, чтобы перед Новым 0 был еще один образец. Итак, если у нас есть ядро 4x4, центрированные индексы должны быть -2 -1 0 +1
. Это верно? А если так, то почему? Может кто-нибудь объяснить, почему -2 -1 0 +1
правильно, а -1 0 +1 +2
нет? Помни, что я хочу ... выполните свертку без использования FFT.
2 ответов
Если я правильно понимаю ваш вопрос, то для ядер четного размера вы правы, что это центрировать ядро так, чтобы перед Новым нулем был еще один образец.
Итак, для ядра шириной 4 центрированные индексы будут -2 -1 0 +1
Как вы сказали выше.
однако это действительно просто соглашение-асимметричная свертка очень редко используется в любом случае и точный характер асимметрии (слева / справа и т. д.) нет отношение к" правильному " результату. Я бы предположил, что причина, по которой большинство реализаций ведут себя таким образом, заключается в том, что они могут давать сопоставимые результаты при одинаковых входных данных.
при выполнении свертки в частотной области ядро все равно дополняется, чтобы соответствовать размеру изображения, и вы уже заявили, что выполняете свертку в пространственной области.
меня гораздо больше интересует, почему вам нужно использовать ядро четного размера в первое место.
правильный ответ-вернуть пиксель результатов в верхнем левом углу, независимо от того, имеет ли ваша матрица равномерный размер или нет. Затем вы можете просто выполнить операцию в простой scanline, и они не требуют памяти.
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) { }
}