Линейное размывание изображения - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь размыть изображение, сопоставляя каждый пиксель со средним из N пикселей справа от него (в той же строке). Мое итеративное решение дает хороший результат, но мое решение по линейной алгебре дает плохой результат.

По результатам тестирования я считаю, что ядро-матрица верна; и я знаю, что последние N строк не размываются, но пока это нормально. Буду признателен за любые советы или решения.

iterative-solution output enter image description here

вывод итеративного решения (хорошо), линейная алгебра вывод (плохо)

enter image description here

исходное изображение; и вот код неисправной линейной алгебры:

def blur(orig_img):
    # turn image-mat into a vector
    flattened_img = orig_img.flatten()
    L = flattened_img.shape[0]
    N = 3

    # kernel
    kernel = np.zeros((L, L))
    for r, row in enumerate(kernel[0:-N]):
        row[r:r+N] = [round(1/N, 3)]*N
    print(kernel)

    # blurr the img
    print('starting blurring')
    blurred_img = np.matmul(kernel, flattened_img)
    blurred_img = blurred_img.reshape(orig_img.shape)
    return blurred_img

Уравнение, которое я моделирую, таково:

enter image description here

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Неправильное использование cv2.imshow() при отображении выходного изображения. Ожидается, что значения пикселей с плавающей точкой будут в [0, 1]; что, делается в следующем коде (в нижней части):

def blur(orig_img):
    flattened_img = orig_img.flatten()
    L = flattened_img.shape[0]
    N = int(round(0.1 * orig_img.shape[0], 0))

    # mask (A)
    mask = np.zeros((L, L))
    for r, row in enumerate(mask[0:-N]):
        row[r:r+N] = [round(1/N, 2)]*N

    # blurred img = A * flattened_img
    print('starting blurring')
    blurred_img = np.matmul(mask, flattened_img)
    blurred_img = blurred_img.reshape(orig_img.shape)
    cv2.imwrite('blurred_img.png', blurred_img)

    # normalize img to [0,1]
    blurred_img = (
        blurred_img - blurred_img.min()) / (blurred_img.max()-blurred_img.min())
    return blurred_img

enter image description here

Исправленный вывод

Спасибо @CrisLuen go для выявления проблемы.

1 голос
/ 31 марта 2020

Одним из вариантов может быть просто использовать ядро ​​и свертку?

Например, если мы загружаем изображение в оттенках серого, например, так:

import numpy as np
import matplotlib.pyplot as plt

from PIL import Image
from scipy import ndimage

# load a hackinsh grayscale image
image = np.asarray(Image.open('cup.jpg')).mean(axis=2)
plt.imshow(image)
plt.title('Gray scale image')
plt.show()

Sample image

Теперь можно использовать ядро ​​и свертку. Например, чтобы создать фильтр, который фильтрует только одну строку и вычислить значение центрального пикселя как разность между пикселями справа и слева, можно сделать следующее:

# Create a kernel that takes the difference between neighbors horizontal pixes
k = np.array([[-1,0,1]])
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')
plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()

Simple edge detector

Таким образом, можно размыть изображение, сопоставив каждый пиксель со средним из N пикселей справа от него, создав соответствующее ядро.

# Create a kernel that takes the average of N pixels to the right
n=10
k = np.zeros(n*2);k[n:]=1/n
k = k[np.newaxis,...]
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')

plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()

right based blur

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...