Свертка с горизонтальным ядром дает странный вывод - PullRequest
1 голос
/ 04 февраля 2020

Итак, я пытаюсь выполнить свертку 2D-изображения, используя горизонтальное ядро ​​3x3, которое выглядит следующим образом:

horizontal = np.array([
                      [0, 0, 0], 
                      [-1, 0, 1], 
                      [0, 0, 0]]),

Так что я использую приведенную ниже функцию свертки, где я зацикливаюсь на изображении, начиная с игнорирования первых нескольких пикселей (размер ядра) и умножения и добавления

def perform_convolution(k_h, k_w, img_h, img_w, kernel, picture):
    # k_w = kernel width, k_h = kernel_height
    # img_h = image height, img_w = image width

    conv = np.zeros(picture.shape)

    for i in range(k_h, img_h - (k_h)):
        for j in range(k_w, img_w - (k_w)):
            tot = 0
            for m in range(k_h):
                for n in range(k_w):
                    tot = tot + kernel[m][n] * picture[i - (k_h) + m][j - (k_w) + n]
            conv[i][j] = tot
    return conv

Но вывод, который я получаю, совершенно странный, как показано ниже

enter image description here

В качестве альтернативы, используя ядро ​​из PIL, я получаю правильное размытое изображение, подобное этому,

enter image description here

Так может ли кто-нибудь помочь мне понять, где я ошибаюсь?

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

Я также пытался разделить полосы RGB и свертывать их отдельно, но безрезультатно.

Исходное изображение таково:

enter image description here

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Во-первых, используемый вами фильтр - это градиентный фильтр, который в этом случае дает значения в диапазоне [-255,255]. Здесь главное, что нужно учитывать, это то, что значение, которое вы получаете, - это не просто величина, вы также указываете направление края. Таким образом, чтобы учесть это, вы можете сохранить информацию о фазе, то есть 0 градусов для положительного значения, 180 градусов для отрицательного значения в другом изображении. Наконец, визуализируя изображение градиента, вы можете просто взглянуть на величину изображения и узнать, что существует фазовое изображение, которое определяет направление градиента.

Во-вторых, слегка сглаженное изображение, которое вы показываете в вопрос не может быть создан с этим ядром.

Также, как правило, когда вы хотите применить плавный фильтр, всегда убедитесь, что сумма всех элементов в ядре равна 1.

0 голосов
/ 04 февраля 2020

вам нужно внести следующие изменения в код, если вы хотите получить изображение, равное размытому изображению в вашем вопросе, за исключением, возможно, краев и диагонального сдвига на 1 или 2 пикселя:

horizontal = np.array([[0.0, 0.0, 0.0], 
                       [0.5, 0.0, 0.5], 
                       [0.0, 0.0, 0.0]])

Более того, не для этого ядра, но если вы хотите увидеть более реалистичный c вывод вашего предыдущего ядра, вам также нужно это изменение:

conv[i][j] = np.clip(tot, 0, 255)

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

np.clip() необходимо точно во избежание переполнений и переполнений (которые не случаются с вашим желаемым ядром, поскольку оно является усредняющим)

ОБНОВЛЕНИЕ:

Вы может тоже нуждаться в этом изменении:

conv = np.zeros(picture.shape, dtype=np.uint8)
...