Сглаживание изображений в Python

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

Как я могу использовать numpy.convolve для сглаживания изображения?

Хороший вопрос! Сообщение tcaswell здесь большое предложение, но вы не будете многому научиться, потому что Scipy делает всю работу за вас! Поскольку в вашем вопросе говорилось, что вы хотите попробовать написать эту функцию , я покажу вам немного более грубый и простой способ сделать все это вручную, надеясь, что вы лучше поймете математику за сверткой и т. Д., А затем вы сможете улучшить это с вашими собственными идеями и усилиями!

Примечание. Вы получите разные результаты с разными формами / размерами ядер, гауссовский обычным способом, но вы можете попробовать некоторые другие для удовольствия (косинус, треугольник и т. Д.!). Я только что сделал это на месте, я думаю, что это своего рода пирамида.

 import scipy.signal import numpy as np import matplotlib.pyplot as plt im = plt.imread('example.jpg') im /= 255. # normalise to 0-1, it's easier to work in float space # make some kind of kernel, there are many ways to do this... t = 1 - np.abs(np.linspace(-1, 1, 21)) kernel = t.reshape(21, 1) * t.reshape(1, 21) kernel /= kernel.sum() # kernel should sum to 1! :) # convolve 2d the kernel with each channel r = scipy.signal.convolve2d(im[:,:,0], kernel, mode='same') g = scipy.signal.convolve2d(im[:,:,1], kernel, mode='same') b = scipy.signal.convolve2d(im[:,:,2], kernel, mode='same') # stack the channels back into a 8-bit colour depth image and plot it im_out = np.dstack([r, g, b]) im_out = (im_out * 255).astype(np.uint8) plt.subplot(2,1,1) plt.imshow(im) plt.subplot(2,1,2) plt.imshow(im_out) plt.show() 

введите описание изображения здесь

Вы хотите посмотреть на ndimage , который является модулем в scipy . Он имеет множество фильтров, все настроенные как функции, и красивые обертки для свертки произвольных ядер.

Например,

 img_gaus = ndimage.filters.gaussian_filter(img, 2, mode='nearest') 

сокрушает ваше изображение с гуасином с сигмой 2.

Если вы хотите свернуть произвольное ядро, скажем, крест

 k = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) img2 = ndimage.convolve(img, k, mode='constant') 

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

Параметры mode и cval управляют тем, как свертки имеют дело с пикселями на краю вашего изображения (для пикселя на краю половина области, на которую нужно смотреть ядро, не существует, поэтому вам нужно выбрать что-то, изображение с).

Если вы не хотите использовать scipy, у вас есть три варианта:

1) вы можете использовать теорему свертки в сочетании с преобразованиями Фурье, поскольку numpy имеет двумерный БПФ.

2) вы можете использовать разделяемое ядро, а затем вы можете сделать две одномерные свертки на сплющенных массивах, одну в направлении x, а другую в направлении y (ravel transpose), и это даст тот же результат, что и 2D свертка.

3) если у вас небольшое ядро, скажем, 3×3, достаточно просто написать свертку как умножения и суммы. Это звучит как хлопот, но это не так уж плохо.

Если вы хотите использовать scipy, вы можете использовать ngimage, как предлагает tcaswell. scipy также имеет convolve2d.