此函数是否正确计算卷积?
Does this function compute convolution correctly?
我需要编写一个基本函数来计算矩阵和内核之间的二维卷积。
我最近进入了Python,所以我为我的错误感到抱歉。
我的论文老师说我应该自己写一篇这样我可以更好地处理它并且能够修改它以便将来改进。
我在网站上找到了这个函数的例子,但是我不明白返回值是怎么得到的。
这是代码(来自 http://docs.cython.org/src/tutorial/numpy.html )
from __future__ import division
import numpy as np
def naive_convolve(f, g):
# f is an image and is indexed by (v, w)
# g is a filter kernel and is indexed by (s, t),
# it needs odd dimensions
# h is the output image and is indexed by (x, y),
# it is not cropped
if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported")
# smid and tmid are number of pixels between the center pixel
# and the edge, ie for a 5x5 filter they will be 2.
#
# The output size is calculated by adding smid, tmid to each
# side of the dimensions of the input image.
vmax = f.shape[0]
wmax = f.shape[1]
smax = g.shape[0]
tmax = g.shape[1]
smid = smax // 2
tmid = tmax // 2
xmax = vmax + 2*smid
ymax = wmax + 2*tmid
# Allocate result image.
h = np.zeros([xmax, ymax], dtype=f.dtype)
# Do convolution
for x in range(xmax):
for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1)
value = 0
for s in range(s_from, s_to):
for t in range(t_from, t_to):
v = x - smid + s
w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value
return h
我不知道这个函数是否对输入和过滤器进行加权求和,因为我在这里看不到求和。
我用
应用了这个
kernel = np.array([(1, 1, -1), (1, 0, -1), (1, -1, -1)])
file = np.ones((5,5))
naive_convolve(file, kernel)
我得到了这个矩阵:
[[ 1. 2. 1. 1. 1. 0. -1.]
[ 2. 3. 1. 1. 1. -1. -2.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 2. 1. -1. -1. -1. -3. -2.]
[ 1. 0. -1. -1. -1. -2. -1.]]
我尝试对函数的第一次完整迭代进行手动计算(在纸上),我得到了 'h[0,0] = 0',因为矩阵乘积:'filter[0, 0] * matrix[0, 0]',但是函数 returns 1. 我对此很困惑。
如果有人可以帮助我了解这里发生了什么,我将不胜感激。谢谢! :)
是的,该函数正确计算了卷积。您可以使用 scipy.signal.convolve2d
进行检查
import numpy as np
from scipy.signal import convolve2d
kernel = np.array([(1, 1, -1), (1, 0, -1), (1, -1, -1)])
file = np.ones((5,5))
x = convolve2d(file, kernel)
print x
给出:
[[ 1. 2. 1. 1. 1. 0. -1.]
[ 2. 3. 1. 1. 1. -1. -2.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 2. 1. -1. -1. -1. -3. -2.]
[ 1. 0. -1. -1. -1. -2. -1.]]
不可能知道如何向您解释这一切,因为我不知道从哪里开始,而且我不知道为什么所有其他解释都不适合您。不过,我认为你正在做所有这些作为学习练习,这样你就可以自己解决这个问题。从我在 SO 上看到的情况来看,在 SO 上提出大问题并不能代替你自己解决问题。
你的具体问题是为什么
h[0,0] = 0
在你的计算中不匹配这个矩阵是一个很好的。事实上,两者都是正确的。不匹配的原因是卷积的输出没有指定的数学索引,而是隐含的。由索引 [0,0]
在数学上表示的中心对应于上面矩阵中的 x[3,3]
。
我需要编写一个基本函数来计算矩阵和内核之间的二维卷积。 我最近进入了Python,所以我为我的错误感到抱歉。 我的论文老师说我应该自己写一篇这样我可以更好地处理它并且能够修改它以便将来改进。 我在网站上找到了这个函数的例子,但是我不明白返回值是怎么得到的。
这是代码(来自 http://docs.cython.org/src/tutorial/numpy.html )
from __future__ import division
import numpy as np
def naive_convolve(f, g):
# f is an image and is indexed by (v, w)
# g is a filter kernel and is indexed by (s, t),
# it needs odd dimensions
# h is the output image and is indexed by (x, y),
# it is not cropped
if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported")
# smid and tmid are number of pixels between the center pixel
# and the edge, ie for a 5x5 filter they will be 2.
#
# The output size is calculated by adding smid, tmid to each
# side of the dimensions of the input image.
vmax = f.shape[0]
wmax = f.shape[1]
smax = g.shape[0]
tmax = g.shape[1]
smid = smax // 2
tmid = tmax // 2
xmax = vmax + 2*smid
ymax = wmax + 2*tmid
# Allocate result image.
h = np.zeros([xmax, ymax], dtype=f.dtype)
# Do convolution
for x in range(xmax):
for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1)
value = 0
for s in range(s_from, s_to):
for t in range(t_from, t_to):
v = x - smid + s
w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value
return h
我不知道这个函数是否对输入和过滤器进行加权求和,因为我在这里看不到求和。 我用
应用了这个kernel = np.array([(1, 1, -1), (1, 0, -1), (1, -1, -1)])
file = np.ones((5,5))
naive_convolve(file, kernel)
我得到了这个矩阵:
[[ 1. 2. 1. 1. 1. 0. -1.]
[ 2. 3. 1. 1. 1. -1. -2.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 2. 1. -1. -1. -1. -3. -2.]
[ 1. 0. -1. -1. -1. -2. -1.]]
我尝试对函数的第一次完整迭代进行手动计算(在纸上),我得到了 'h[0,0] = 0',因为矩阵乘积:'filter[0, 0] * matrix[0, 0]',但是函数 returns 1. 我对此很困惑。 如果有人可以帮助我了解这里发生了什么,我将不胜感激。谢谢! :)
是的,该函数正确计算了卷积。您可以使用 scipy.signal.convolve2d
import numpy as np
from scipy.signal import convolve2d
kernel = np.array([(1, 1, -1), (1, 0, -1), (1, -1, -1)])
file = np.ones((5,5))
x = convolve2d(file, kernel)
print x
给出:
[[ 1. 2. 1. 1. 1. 0. -1.]
[ 2. 3. 1. 1. 1. -1. -2.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 3. 3. 0. 0. 0. -3. -3.]
[ 2. 1. -1. -1. -1. -3. -2.]
[ 1. 0. -1. -1. -1. -2. -1.]]
不可能知道如何向您解释这一切,因为我不知道从哪里开始,而且我不知道为什么所有其他解释都不适合您。不过,我认为你正在做所有这些作为学习练习,这样你就可以自己解决这个问题。从我在 SO 上看到的情况来看,在 SO 上提出大问题并不能代替你自己解决问题。
你的具体问题是为什么
h[0,0] = 0
在你的计算中不匹配这个矩阵是一个很好的。事实上,两者都是正确的。不匹配的原因是卷积的输出没有指定的数学索引,而是隐含的。由索引 [0,0]
在数学上表示的中心对应于上面矩阵中的 x[3,3]
。