Scipy convolve2d 与 Theano 的 conv2d 一样具有子采样?
Scipy convolve2d with subsampling like Theano's conv2d?
我希望使用 10 X 10 过滤器对大小为 600 X 400 的图像执行二维卷积。过滤器不可分离。 scipy.signal.convolve2d
目前对我来说效果很好,但我期待很快会有更大的图像。
为了解决这个问题,我有两个想法
- 调整图片大小
- 子采样(或跨步)?
着眼于子采样部分,theano有一个函数和scipy convolve2d一样做卷积,见theano conv2d
它也有子采样选项。但是,在 windows 上安装 theano 对我来说很痛苦。如何使用 scipy.signal.convolve2d
进行子采样?还有其他选择吗(不需要我安装一些重量级库)?
您可以手动实现子采样,为了简单起见,我只绘制 1d。假设您想在间距为 k 的常规子网格上采样 s = d * f。那么你的第n个样本就是s_nk = sum_i=0^10 f_i d_nk-i。这里要注意的是 f 和 d 的索引总和为 k 的倍数。这建议将其拆分为 sub-sums s_nk = sum_j=0^k-1 sum_i=0^10/k f_j+ik d_-j+(n-i)k。所以你需要做的是:在所有偏移量为 0,...,k-1 的间距为 k 的网格上对 d 和 f 进行子采样。对偏移总和为 0 或 k 的所有二次采样 d 和 f 对进行卷积,然后将结果相加。
这是 1d 的一些代码。它大致实现了上述内容,只是网格的位置略有不同,以使索引管理更容易。第二个函数以愚蠢的方式进行,即计算完整的卷积然后抽取。它用于测试第一个功能。
import numpy as np
from scipy import signal
def ss_conv(d1, d2, decimate):
n = (len(d1) + len(d2) - 1) // decimate
out = np.zeros((n,))
for i in range(decimate):
d1d = d1[i::decimate]
d2d = d2[decimate-i-1::decimate]
cv = signal.convolve(d1d, d2d, 'full')
out[:len(cv)] += cv
return out
def conv_ss(d1, d2, decimate):
return signal.convolve(d1, d2, 'full')[decimate-1::decimate]
编辑:2d 版本:
import numpy as np
from scipy import signal
def ss_conv_2d(d1, d2, decy, decx):
ny = (d1.shape[0] + d2.shape[0] - 1) // decy
nx = (d1.shape[1] + d2.shape[1] - 1) // decx
out = np.zeros((ny, nx))
for i in range(decy):
for j in range(decx):
d1d = d1[i::decy, j::decx]
d2d = d2[decy-i-1::decy, decx-j-1::decx]
cv = signal.convolve2d(d1d, d2d, 'full')
out[:cv.shape[0], :cv.shape[1]] += cv
return out
def conv_ss_2d(d1, d2, decy, decx):
return signal.convolve2d(d1, d2, 'full')[decy-1::decy, decx-1::decx]
我希望使用 10 X 10 过滤器对大小为 600 X 400 的图像执行二维卷积。过滤器不可分离。 scipy.signal.convolve2d
目前对我来说效果很好,但我期待很快会有更大的图像。
为了解决这个问题,我有两个想法
- 调整图片大小
- 子采样(或跨步)?
着眼于子采样部分,theano有一个函数和scipy convolve2d一样做卷积,见theano conv2d
它也有子采样选项。但是,在 windows 上安装 theano 对我来说很痛苦。如何使用 scipy.signal.convolve2d
进行子采样?还有其他选择吗(不需要我安装一些重量级库)?
您可以手动实现子采样,为了简单起见,我只绘制 1d。假设您想在间距为 k 的常规子网格上采样 s = d * f。那么你的第n个样本就是s_nk = sum_i=0^10 f_i d_nk-i。这里要注意的是 f 和 d 的索引总和为 k 的倍数。这建议将其拆分为 sub-sums s_nk = sum_j=0^k-1 sum_i=0^10/k f_j+ik d_-j+(n-i)k。所以你需要做的是:在所有偏移量为 0,...,k-1 的间距为 k 的网格上对 d 和 f 进行子采样。对偏移总和为 0 或 k 的所有二次采样 d 和 f 对进行卷积,然后将结果相加。
这是 1d 的一些代码。它大致实现了上述内容,只是网格的位置略有不同,以使索引管理更容易。第二个函数以愚蠢的方式进行,即计算完整的卷积然后抽取。它用于测试第一个功能。
import numpy as np
from scipy import signal
def ss_conv(d1, d2, decimate):
n = (len(d1) + len(d2) - 1) // decimate
out = np.zeros((n,))
for i in range(decimate):
d1d = d1[i::decimate]
d2d = d2[decimate-i-1::decimate]
cv = signal.convolve(d1d, d2d, 'full')
out[:len(cv)] += cv
return out
def conv_ss(d1, d2, decimate):
return signal.convolve(d1, d2, 'full')[decimate-1::decimate]
编辑:2d 版本:
import numpy as np
from scipy import signal
def ss_conv_2d(d1, d2, decy, decx):
ny = (d1.shape[0] + d2.shape[0] - 1) // decy
nx = (d1.shape[1] + d2.shape[1] - 1) // decx
out = np.zeros((ny, nx))
for i in range(decy):
for j in range(decx):
d1d = d1[i::decy, j::decx]
d2d = d2[decy-i-1::decy, decx-j-1::decx]
cv = signal.convolve2d(d1d, d2d, 'full')
out[:cv.shape[0], :cv.shape[1]] += cv
return out
def conv_ss_2d(d1, d2, decy, decx):
return signal.convolve2d(d1, d2, 'full')[decy-1::decy, decx-1::decx]