алгоритм маскированного сглаживания numpy
У меня есть алгоритм сглаживания, который я реализовал, который в основном применяет ядро:
[0 1 0;
1 4 1;
0 1 0]/8
К матрице (изображению) и затем исправляет ребра и углы, что эквивалентно установке ядра как
[0 1 0;
0 5 1;
0 1 0]/8
Для левого края и
[0 0 0;
0 6 1;
0 1 0]/8
Для верхнего левого угла.
Теперь моя цель - применить сглаживание, которое применимо только к замаскированной части этого изображения. Например (см. изображения ниже), если бы у меня был квадратный образ диска, где диск имел бы значения 128+-10 (+-10-шумовой эффект), а фон черный (значение 0), нормальный алгоритм сглаживания, применяемый бесконечное число раз, должен дать квадратное изображение с постоянной интенсивностью пикселей. Для алгоритма маскированного сглаживания я хотел бы замаскировать диск таким образом, чтобы алгоритм, применяемый бесконечное время, давал равномерный диск на 128 и черный (0) фон. Другими словами, разглаживался только диск.
Главное, чего я пытаюсь избежать, это то, что фон "кровоточит" в диск, делая края диска нечеткими. Я также готов изменить алгоритм сглаживания на что-то другое (например. в среднем 3x3 пикселя), что позволило бы использовать более эффективный подход.
( после маскированной гладкой)
Вот мой код для нормальной гладкости:
def SmoothImage(Matrix,N=1):
'''Smooths a Matrix with kernel [0 1 0; 1 4 1; 0 1 0]/8'''
A=Matrix.copy()
for i in range(N):
s=A.shape[0]-1
B=A*4.0
B[-s:,:]+=A[:s,:]
B[0,:]+=A[0,:]
B[:,-s:]+=A[:,:s]
B[:,0]+=A[:,0]
B[:s,:]+=A[-s:,:]
B[-1,:]+=A[-1,:]
B[:,:s]+=A[:,-s:]
B[:,-1]+=A[:,-1]
B*=1/8
A=B
return A
2 ответов:
Вот один подход, использующий линейную свертку плюс некоторые хитрости для сохранения чистых краев. Хитрость в основном вычисляет массу, потерянную на краях, свернув с обратной маской и добавляя ее к исходному результату:
import numpy as np from scipy.signal import convolve2d kernel = np.add.outer(*2*(np.arange(3) % 2,))**2 / 8 def perfect_edges(orig, n_iter=1, thresh=20): mask = orig <= thresh corrector = convolve2d(mask, kernel, 'same') result = orig.copy() result[mask] = 0 for j in range(n_iter): result = result * corrector + convolve2d(result, kernel, 'same') result[mask] = 0 result = np.round(result).astype(np.uint8) result[mask] = orig[mask] return result picture = (np.add.outer(*2*(np.arange(-6, 7)**2,)) < 30).view(np.uint8) * 118 picture += np.random.randint(0, 21, picture.shape, dtype=np.uint8) print(picture) print() print(perfect_edges(picture, 200))Пример выполнения:
[[ 15 0 4 10 17 13 20 12 14 1 5 16 19] [ 1 6 9 14 132 132 129 128 135 1 5 11 5] [ 13 16 6 126 118 118 134 120 130 138 2 6 10] [ 16 3 129 129 128 129 125 134 131 132 127 18 8] [ 10 120 132 125 128 120 133 137 125 120 124 129 7] [ 10 137 119 120 119 118 137 135 135 126 118 128 0] [ 17 134 138 133 134 121 124 119 134 138 133 129 2] [ 3 134 136 132 119 124 123 133 126 121 126 122 19] [ 3 123 130 123 125 125 128 119 119 129 119 127 6] [ 5 0 119 118 125 122 135 135 126 133 136 7 3] [ 11 1 13 124 121 118 136 137 127 137 2 19 15] [ 6 7 15 19 132 132 130 125 130 9 18 9 12] [ 16 20 0 14 9 10 1 6 5 17 16 0 3]] [[ 15 0 4 10 17 13 20 12 14 1 5 16 19] [ 1 6 9 14 128 128 128 128 128 1 5 11 5] [ 13 16 6 128 128 128 128 128 128 128 2 6 10] [ 16 3 128 128 128 128 128 128 128 128 128 18 8] [ 10 128 128 128 128 128 128 128 128 128 128 128 7] [ 10 128 128 128 128 128 128 128 128 128 128 128 0] [ 17 128 128 128 128 128 128 128 128 128 128 128 2] [ 3 128 128 128 128 128 128 128 128 128 128 128 19] [ 3 128 128 128 128 128 128 128 128 128 128 128 6] [ 5 0 128 128 128 128 128 128 128 128 128 7 3] [ 11 1 13 128 128 128 128 128 128 128 2 19 15] [ 6 7 15 19 128 128 128 128 128 9 18 9 12] [ 16 20 0 14 9 10 1 6 5 17 16 0 3]]
scipy.ndimage.convolve()это то, чего ты хочешь. Чтобы выполнить свертку с маской, вызовитеconvolve()с изображением и маской, а затем выполните деление:import numpy as np from scipy import ndimage img = np.random.rand(100, 100) X, Y = np.mgrid[0:100, 0:100] mask = (((X - 50)**2 + (Y - 50)**2)**0.5 < 30).astype(np.int8) img[mask == 0] = 0 kernel = np.array([ [0, 1, 0], [1, 4, 1], [0, 1, 0]]) neighbour_count = ndimage.convolve(mask, kernel, mode="constant") m = neighbour_count > 0 for i in range(10): img = ndimage.convolve(img, kernel, mode="constant") img[m] /= neighbour_count[m] img[mask == 0] = 0 pl.imshow(img)Вывод:



Comments