issue1: 在正常的CNN中,一般使用的都是learned conv weights ,这样不需要我们去做任何的干涉和操作;可在部分时候也需要自定义一些特殊的运算,比如获取图像的梯度(sobel算子),获取blur图像以此搭建pyramid images。使用卷积操作既可以大大契合需求,在CNN中也能加快运算。
实际操作:使用
F.conv2d(xx, k, stride=stride, padding=0) xx是输入,k是自定义的卷积核。
其实只是提取获取好xx & k, 然后将其转换成tensor形式,然后套入F.conv2d 运算即可。
def get_gaussian_kernel(size=3): # 获取高斯kerner 并转为tensor ,size 可以改变模糊程度
kernel = cv2.getGaussianKernel(size, 0).dot(cv2.getGaussianKernel(size, 0).T)
kernel = torch.FloatTensor(kernel).unsqueeze(0).unsqueeze(0)
kernel = torch.nn.Parameter(data=kernel, requires_grad=False)
return kernel
def get_sobel_kernel(im):
sobel_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32')
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))
weight = Variable(torch.from_numpy(sobel_kernel))
????return weight
两种形式都是一样的,提前获取好,然后再转换成tensor 就好。
im = Image.open('./cat.jpg').convert('L')
# 将图片数据转换为矩阵
im = np.array(im, dtype='float32')
# 将图片矩阵转换为pytorch tensor,并适配卷积输入的要求
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
????????
def gaussian_blur(x, k, stride=1, padding=0):
res = []
x = F.pad(x, (padding, padding, padding, padding), mode='constant', value=0)
for xx in x.split(1, 1):
res.append(F.conv2d(xx, k, stride=stride, padding=0))
return torch.cat(res, 1)
gauss_kernel = get_gaussian_kernel(size=9)
low_gray = gaussian_blur(im, gauss_kernel, padding=0)
def functional_conv2d(im):
sobel_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32') #
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))
weight = Variable(torch.from_numpy(sobel_kernel))
print('weight.size()',weight.size())
edge_detect = F.conv2d(Variable(im), weight)
print('edge_detect.size()', edge_detect.size())
edge_detect = edge_detect.squeeze().detach().numpy()
print('edge_detect.size()', edge_detect.shape)
return edge_detect
edge_detect = functional_conv2d(im)
运行结果展示:
??
?
issue2:? pytorch 中FFT
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
print('input size:',im.size())
fft = torch.rfft(im, 2, onesided=False)
print('fft[..., 0]',fft[..., 0].size())
print('fft',fft.size())
?输出:
输出:
size: torch.Size([1, 1, 360, 600])
fft[..., 0] 是实部 fft[..., 1] 是虚部
torch.Size([1, 1, 360, 600])
fft
torch.Size([1, 1, 360, 600, 2])
获取幅度:torch.sqrt(fft[..., 0] ** 2 + fft[..., 1] ** 2 + 1e-8)
?
|