2d свертка с использованием Python и NumPy - PullRequest
14 голосов
/ 15 марта 2010

Я пытаюсь выполнить 2-мерную свертку в python, используя numpy

У меня есть 2d-массив следующим образом с ядром H_r для строк и H_c для столбцов

data = np.zeros((nr, nc), dtype=np.float32)

#fill array with some data here then convolve

for r in range(nr):
    data[r,:] = np.convolve(data[r,:], H_r, 'same')

for c in range(nc):
    data[:,c] = np.convolve(data[:,c], H_c, 'same')

data = data.astype(np.uint8);

Он не выдает ожидаемого результата, этот код выглядит нормально, я думаю, что проблема в преобразовании с float32 в 8bit. Какой лучший способ сделать это

Спасибо

Ответы [ 5 ]

5 голосов
/ 04 октября 2016

Редактировать [январь 2019]

@ Комментарий Ташуса ниже верен, и, таким образом, @ ответ dudemeister , таким образом, вероятно, более заметен. Предложенная им функция также более эффективна, поскольку позволяет избежать прямой двумерной свертки и количества операций, которые могут повлечь за собой.

Возможная проблема

Я полагаю, что вы делаете два 1d свертки, первое для столбцов и второе для строк, и заменяете результаты первого на результаты второго.

Обратите внимание, что numpy.convolve с аргументом 'same' возвращает массив, равный по величине предоставленному наибольшему, поэтому при первом свертывании вы уже заполнили весь массив data.

Одним из хороших способов визуализации ваших массивов на этих этапах является использование диаграмм Хинтона , чтобы вы могли проверить, какие элементы уже имеют значение.

Возможное решение

Вы можете попытаться добавить результаты двух сверток (используйте data[:,c] += .. вместо data[:,c] = во втором цикле for), если ваша матрица свертки является результатом использования одномерных H_r и H_c таких матриц как:

convolution core addition

Еще один способ сделать это - использовать scipy.signal.convolve2d с 2-мерным свёрточным массивом, что, пожалуй, то, что вы хотели сделать в первую очередь.

5 голосов
/ 15 марта 2010

Поскольку ваше ядро ​​уже отделено, вы должны просто использовать функцию sepfir2d из scipy:

from scipy.signal import sepfir2d
convolved = sepfir2d(data, H_r, H_c)

С другой стороны, код, который у вас там, выглядит хорошо ...

4 голосов
/ 03 марта 2017

Возможно, это не самое оптимизированное решение, но это реализация, которую я использовал ранее с библиотекой numpy для Python:

def convolution2d(image, kernel, bias):
    m, n = kernel.shape
    if (m == n):
        y, x = image.shape
        y = y - m + 1
        x = x - m + 1
        new_image = np.zeros((y,x))
        for i in range(y):
            for j in range(x):
                new_image[i][j] = np.sum(image[i:i+m, j:j+m]*kernel) + bias
return new_image

Надеюсь, этот код поможет другим парням с таким же сомнением.

С уважением.

0 голосов
/ 03 июля 2015

Этот код неверен:

for r in range(nr):
    data[r,:] = np.convolve(data[r,:], H_r, 'same')

for c in range(nc):
    data[:,c] = np.convolve(data[:,c], H_c, 'same')

См. Преобразование Нуссбаумера из многомерной свертки в одномерную.

0 голосов
/ 30 января 2013

Попробуйте первый раунд, а затем приведите к uint8:

data = data.round().astype(np.uint8);
...