我实现了一个平滑算法,它基本上应用了一个内核:
[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像素),这将允许更有效的方法。

(嘈杂的原稿)

(在法线平滑之后)

(在遮罩平滑之后)
下面是我的normal smooth代码:
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发布于 2018-02-22 09:10:08
这里是一种使用线性卷积和一些技巧来保持干净边缘的方法。该技巧主要是通过与逆掩码卷积来计算边缘损失的质量,并将其添加到原始结果中:
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]]发布于 2018-02-22 09:14:13
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)输出:

https://stackoverflow.com/questions/48917761
复制相似问题