卷积算法的简单实现
Naive Implementation of Convolution algorithm
目前正在通过斯坦福 CS131 的免费在线课程学习计算机视觉和机器学习。遇到了一些繁重的数学公式,想知道是否有人可以向我解释如何在只知道图像高度、宽度和内核高度和宽度的情况下为卷积算法实现一个朴素的 4 嵌套 for 循环。我能够通过在线研究提出这个解决方案。
image_padded = np.zeros((image.shape[0] + 2, image.shape[1] + 2))
image_padded[1:-1, 1:-1] = image
for x in range(image.shape[1]): # Loop over every pixel of the image
for y in range(image.shape[0]):
# element-wise multiplication of the kernel and the image
out[y, x] = (kernel * image_padded[y:y + 3, x:x + 3]).sum()
基于一些使用此类算法的网站示例,我能够理解这一点,但是,我似乎无法理解 4 个嵌套的 for 循环是如何做到的。如果可以的话,将公式分解成比网上找到的给定数学方程式更容易理解的东西。
编辑:
只是为了澄清我留下的代码片段在一定程度上起作用,我正在尝试提出一个优化程度较低但对初学者更友好的解决方案,例如此代码所要求的内容:
def conv_nested(image, kernel):
"""A naive implementation of convolution filter.
This is a naive implementation of convolution using 4 nested for-loops.
This function computes convolution of an image with a kernel and outputs
the result that has the same shape as the input image.
Args:
image: numpy array of shape (Hi, Wi)
kernel: numpy array of shape (Hk, Wk)
Returns:
out: numpy array of shape (Hi, Wi)
"""
Hi, Wi = image.shape
Hk, Wk = kernel.shape
out = np.zeros((Hi, Wi))
### YOUR CODE HERE
### END YOUR CODE
return out
对于这个任务 scipy.signal.correlate2d
是你的朋友。
演示
我将您的代码包装在一个名为 naive_correlation
:
的函数中
import numpy as np
def naive_correlation(image, kernel):
image_padded = np.zeros((image.shape[0] + 2, image.shape[1] + 2))
image_padded[1:-1, 1:-1] = image
out = np.zeros_like(image)
for x in range(image.shape[1]):image
for y in range(image.shape[0]):
out[y, x] = (kernel * image_padded[y:y + 3, x:x + 3]).sum()
return out
请注意,您的代码段会引发错误,因为 out
未初始化。
In [67]: from scipy.signal import correlate2d
In [68]: img = np.array([[3, 9, 5, 9],
...: [1, 7, 4, 3],
...: [2, 1, 6, 5]])
...:
In [69]: kernel = np.array([[0, 1, 0],
...: [0, 0, 0],
...: [0, -1, 0]])
...:
In [70]: res1 = correlate2d(img, kernel, mode='same')
In [71]: res1
Out[71]:
array([[-1, -7, -4, -3],
[ 1, 8, -1, 4],
[ 1, 7, 4, 3]])
In [72]: res2 = naive_correlation(img, kernel)
In [73]: np.array_equal(res1, res2)
Out[73]: True
如果您希望执行卷积而不是相关,您可以使用 convolve2d
。
编辑
这是您要找的吗?
def explicit_correlation(image, kernel):
hi, wi= image.shape
hk, wk = kernel.shape
image_padded = np.zeros(shape=(hi + hk - 1, wi + wk - 1))
image_padded[hk//2:-hk//2, wk//2:-wk//2] = image
out = np.zeros(shape=image.shape)
for row in range(hi):
for col in range(wi):
for i in range(hk):
for j in range(wk):
out[row, col] += image_padded[row + i, col + j]*kernel[i, j]
return out
目前正在通过斯坦福 CS131 的免费在线课程学习计算机视觉和机器学习。遇到了一些繁重的数学公式,想知道是否有人可以向我解释如何在只知道图像高度、宽度和内核高度和宽度的情况下为卷积算法实现一个朴素的 4 嵌套 for 循环。我能够通过在线研究提出这个解决方案。
image_padded = np.zeros((image.shape[0] + 2, image.shape[1] + 2))
image_padded[1:-1, 1:-1] = image
for x in range(image.shape[1]): # Loop over every pixel of the image
for y in range(image.shape[0]):
# element-wise multiplication of the kernel and the image
out[y, x] = (kernel * image_padded[y:y + 3, x:x + 3]).sum()
基于一些使用此类算法的网站示例,我能够理解这一点,但是,我似乎无法理解 4 个嵌套的 for 循环是如何做到的。如果可以的话,将公式分解成比网上找到的给定数学方程式更容易理解的东西。
编辑: 只是为了澄清我留下的代码片段在一定程度上起作用,我正在尝试提出一个优化程度较低但对初学者更友好的解决方案,例如此代码所要求的内容:
def conv_nested(image, kernel):
"""A naive implementation of convolution filter.
This is a naive implementation of convolution using 4 nested for-loops.
This function computes convolution of an image with a kernel and outputs
the result that has the same shape as the input image.
Args:
image: numpy array of shape (Hi, Wi)
kernel: numpy array of shape (Hk, Wk)
Returns:
out: numpy array of shape (Hi, Wi)
"""
Hi, Wi = image.shape
Hk, Wk = kernel.shape
out = np.zeros((Hi, Wi))
### YOUR CODE HERE
### END YOUR CODE
return out
对于这个任务 scipy.signal.correlate2d
是你的朋友。
演示
我将您的代码包装在一个名为 naive_correlation
:
import numpy as np
def naive_correlation(image, kernel):
image_padded = np.zeros((image.shape[0] + 2, image.shape[1] + 2))
image_padded[1:-1, 1:-1] = image
out = np.zeros_like(image)
for x in range(image.shape[1]):image
for y in range(image.shape[0]):
out[y, x] = (kernel * image_padded[y:y + 3, x:x + 3]).sum()
return out
请注意,您的代码段会引发错误,因为 out
未初始化。
In [67]: from scipy.signal import correlate2d
In [68]: img = np.array([[3, 9, 5, 9],
...: [1, 7, 4, 3],
...: [2, 1, 6, 5]])
...:
In [69]: kernel = np.array([[0, 1, 0],
...: [0, 0, 0],
...: [0, -1, 0]])
...:
In [70]: res1 = correlate2d(img, kernel, mode='same')
In [71]: res1
Out[71]:
array([[-1, -7, -4, -3],
[ 1, 8, -1, 4],
[ 1, 7, 4, 3]])
In [72]: res2 = naive_correlation(img, kernel)
In [73]: np.array_equal(res1, res2)
Out[73]: True
如果您希望执行卷积而不是相关,您可以使用 convolve2d
。
编辑
这是您要找的吗?
def explicit_correlation(image, kernel):
hi, wi= image.shape
hk, wk = kernel.shape
image_padded = np.zeros(shape=(hi + hk - 1, wi + wk - 1))
image_padded[hk//2:-hk//2, wk//2:-wk//2] = image
out = np.zeros(shape=image.shape)
for row in range(hi):
for col in range(wi):
for i in range(hk):
for j in range(wk):
out[row, col] += image_padded[row + i, col + j]*kernel[i, j]
return out