寻求无Padding的CNN Sobel滤波器实现方案
解决方案
首先,你使用的nd.sobel(推测为MXNet的ndarray.sobel)本身没有直接提供无Padding(valid模式)的选项,但可以通过两种方式实现无Padding的Sobel滤波需求:
方式一:裁剪带Padding的结果
nd.sobel默认用'reflect' Padding时,会在图像四周各添加1层像素(因Sobel是3x3核)。你可以在得到结果后,手动裁剪掉这部分Padding区域,得到仅由原图像完全覆盖区域计算出的特征图:
修改你的apply_kernel方法:
def apply_kernel(self): # 获取带reflect padding的sobel结果 sobel_with_pad = nd.sobel(input=self.image, mode='reflect') # 裁剪四周各1层的padding,得到无padding的特征图 # 若图像是通道在后格式((H,W,C)),则改为sobel_with_pad[1:-1, 1:-1, :] self.feature_map = sobel_with_pad[:, 1:-1, 1:-1] return self.feature_map
方式二:手动实现无Padding的Sobel卷积
如果更贴合你从零实现CNN的学习目标,可以直接定义Sobel核,用nd.convolution并设置pad=(0,0)来完全手动控制卷积过程:
def apply_kernel(self): # 定义x、y方向的Sobel核 sobel_x = nd.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]).reshape((1, 1, 3, 3)) sobel_y = nd.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]).reshape((1, 1, 3, 3)) # 对多通道图像逐通道处理 channels = [] for c in range(self.image.shape[0]): channel = self.image[c:c+1, :, :] conv_x = nd.convolution(channel, sobel_x, pad=(0,0), num_filter=1) conv_y = nd.convolution(channel, sobel_y, pad=(0,0), num_filter=1) # 合并x、y方向梯度(取L2范数) channel_sobel = nd.sqrt(conv_x**2 + conv_y**2) channels.append(channel_sobel) self.feature_map = nd.concat(*channels, dim=0) return self.feature_map
另外,你的ReLU实现可以用向量化操作优化,避免三重循环以提升效率:
def relu(self): self.post_fm = np.maximum(0.0, self.feature_map.asnumpy()) return self.post_fm
内容的提问来源于stack exchange,提问作者Massimo Giuseppe Ridella
相关产品推荐
相关产品推荐

