pytorch | 计算图像的一阶导/梯度/gradient

本文介绍了在PyTorch中计算图像的一阶导数和梯度,特别是在图像转换任务中的应用,如total variation loss。通过参考numpy源码并使用torch.nn.functional.pad()函数,作者实现了一个计算图像一阶导数的方法。然而,在尝试将图像的梯度作为损失函数进行反向传播时,遇到了梯度爆炸的问题,即使调整loss权重和学习率也无法避免。

[pytorch] 计算图像的一阶导 / 梯度 / gradient

在图像转换任务中常见的total variation loss(tvloss,总变分,一般作为平滑的规则化项)需要对图像的梯度求平方和。
style-transfer系的github项目,tvloss求法如下:

class TVLoss(torch.nn.Module):
    def __init__(self):
        super(TVLoss,self).__init__()

    def forward(self,x):
        h_x = x.size()[2]
        w_x = x.size()[3]
        count_h = self._tensor_size(x[:,:,1:,:])
        count_w = self._tensor_size(x[:,:,:,1:])
        h_tv = torch.pow((x[:,:,1:,:]-x[:,:,:h_x-1,:]),2).sum()
        w_tv = torch.pow((x[:,:,:,1:]-x[:,:,:,:w_x-1
### 如何在 PyTorch实现 Canny 算子 #### 使用 Sobel 滤波器提取梯度 为了实现PyTorch 中的 Canny 边缘检测,首先需要定义用于计算图像梯度幅度和方向的 Sobel 滤波器。通过 `torch.nn.functional.conv2d` 函数可以方便地应用这些滤波器。 ```python import torch import torch.nn as nn import torch.nn.functional as F def get_sobel_kernel(k=3): range_val = torch.linspace(-(k // 2), k // 2, k) x, y = torch.meshgrid(range_val, range_val) sobel_2D_numerator = x sobel_2D_denominator = (x ** 2 + y ** 2) sobel_2D_denominator[:, k // 2] = 1 # 防止除零错误 sobel_2D = sobel_2D_numerator / sobel_2D_denominator return sobel_2D.unsqueeze(0).unsqueeze(0) # 增加维度以便于后续操作 sobel_x = get_sobel_kernel() sobel_y = get_sobel_kernel().transpose(-2, -1) # 转置得到垂直方向上的Sobel核 ``` #### 计算梯度幅值与角度 接着利用上述创建好的 Sobel 核来获取输入张量(通常是灰度化后的图像)沿 X 和 Y 方向的一阶导数,并据此梯度大小及其方位角: ```python class GradientMagnitude(nn.Module): def __init__(self): super().__init__() def forward(self, img_tensor): grad_x = F.conv2d(img_tensor, sobel_x.cuda(), padding='same') grad_y = F.conv2d(img_tensor, sobel_y.cuda(), padding='same') magnitude = torch.sqrt(grad_x ** 2 + grad_y ** 2) angle = torch.atan2(grad_y, grad_x) * (180 / np.pi) % 180 return magnitude, angle ``` #### 应用高斯模糊和平滑处理 考虑到噪声可能会影响最终效果,在实际应用之前通常会对原始数据施加定程度的平滑预处理——即所谓的 Gaussian Blur 或者说是 Gauss Filter。此过程有助于减少不必要的细节干扰并增强主要结构特征的表现力[^5]。 ```python from scipy.ndimage import gaussian_filter def apply_gaussian_blur(image, sigma=1.0): blurred_image = gaussian_filter(image.cpu().numpy(), sigma=sigma) return torch.tensor(blurred_image).cuda() blurred_img = apply_gaussian_blur(input_image) grad_magnitude, _ = gradient_module(blurred_img) ``` #### 完整流程集成 最后步就是把以上各个组件组合起来形成完整的 Canny Edge Detection Pipeline 。值得注意的是这里省略了些诸如非极大抑制(NMS),双阈值选取以及滞后连接等具体步骤;读者可以根据需自行补充完善整个算法逻辑[^4]。 ```python class CannyEdgeDetector(nn.Module): def __init__(self, low_threshold=0.1, high_threshold=0.2): super(CannyEdgeDetector, self).__init__() self.low_threshold = low_threshold self.high_threshold = high_threshold self.gradient_module = GradientMagnitude() def forward(self, input_tensor): # Step 1: Apply Gaussian Blurring to reduce noise and smooth the image. smoothed_input = apply_gaussian_blur(input_tensor) # Step 2: Compute gradients using Sobel filters. magnitudes, angles = self.gradient_module(smoothed_input) # ... Additional steps like NMS, double thresholding etc. edges = None # Placeholder for final edge map after all processing stages. return edges ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值