使用Python和NumPy进行二维卷积
我正在尝试在Python中使用numpy进行二维卷积。
我有一个二维数组,行的卷积核是H_r,列的卷积核是H_c。
data = np.zeros((nr, nc), dtype=np.float32)
#fill array with some data here then convolve
for r in range(nr):
data[r,:] = np.convolve(data[r,:], H_r, 'same')
for c in range(nc):
data[:,c] = np.convolve(data[:,c], H_c, 'same')
data = data.astype(np.uint8);
但是输出结果并不是我预期的那样,这段代码看起来还好吗?我觉得问题可能出在从float32转换到8位整数上。有什么好的方法来解决这个问题吗?
谢谢!
11 个回答
5
既然你已经把内核分开了,那么你可以直接使用scipy里的sepfir2d函数:
from scipy.signal import sepfir2d
convolved = sepfir2d(data, H_r, H_c)
另一方面,你那段代码看起来也没什么问题……
7
编辑 [2019年1月]
@Tashus 下面的评论是对的,@dudemeister 的回答 可能更准确。他建议的函数效率更高,因为它避免了直接进行二维卷积和由此产生的大量运算。
可能的问题
我觉得你在做两次一维卷积,第一次是针对列,第二次是针对行,然后用第二次的结果替换第一次的结果。
注意,使用 numpy.convolve
并加上 'same'
参数时,会返回一个和最大的输入数组形状相同的数组,所以当你进行第一次卷积时,整个 data
数组已经被填满了。
在这些步骤中,一个很好的可视化方法是使用 Hinton 图,这样你可以检查哪些元素已经有值了。
可能的解决方案
你可以尝试将两次卷积的结果相加(在第二个 for
循环中使用 data[:,c] += ..
而不是 data[:,c] =
),如果你的卷积矩阵是使用一维的 H_r
和 H_c
矩阵得到的,像这样:
另一种方法是使用 scipy.signal.convolve2d
进行二维卷积,这可能是你最初想要做的。
26
这可能不是最优的解决方案,但这是我之前用Python的numpy库实现的一个例子:
def convolution2d(image, kernel, bias):
m, n = kernel.shape
if (m == n):
y, x = image.shape
y = y - m + 1
x = x - m + 1
new_image = np.zeros((y,x))
for i in range(y):
for j in range(x):
new_image[i][j] = np.sum(image[i:i+m, j:j+m]*kernel) + bias
return new_image
希望这段代码能帮助到有同样疑问的朋友们。
祝好。