Calculate the gradient of images

Ford: <p>I would like to calculate the gradient map of an image, which is the difference between adjacent pixels. I need to use the gradient maps as loss functions for back propagation to update network parameters, like TV Loss used in style transfer. Now I am confused about  two implementation methods on the Internet.<br>
The first is:</p>
<blockquote>
<p>import torch<br>
import torch.nn.functional as F</p>
<p>def gradient_1order(x,h_x=None,w_x=None):</p>
<pre><code> if h_x is None and w_x is None:
   h_x = x.size()[2]
   w_x = x.size()[3]

 r  = F.pad(x, (0, 1, 0, 0))[:, :, :, 1:]
 l = F.pad(x, (1, 0, 0, 0))[:, :, :, :w_x]
 t = F.pad(x, (0, 0, 1, 0))[:, :, :h_x, :]
 b = F.pad(x, (0, 0, 0, 1))[:, :, 1:, :]
 xgrad = torch.pow(torch.pow((r - l) * 0.5, 2) + torch.pow((t - b) * 0.5, 2), 0.5)
 return xgrad
</code></pre>
</blockquote>
<p>While the second is :</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import torch.nn.functional as F
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class Gradient_Net(nn.Module):

  def __init__(self):

    super(Gradient_Net, self).__init__()
    kernel_x = [[-1., 0., 1.], [-2., 0., 2.], [-1., 0., 1.]]
    kernel_x = torch.FloatTensor(kernel_x).unsqueeze(0).unsqueeze(0).to(device)
    kernel_y = [[-1., 0., 1.], [-2., 0., 2.], [-1., 0., 1.]]
    kernel_y = torch.FloatTensor(kernel_y).unsqueeze(0).unsqueeze(0).to(device)
    self.weight_x = nn.Parameter(data=kernel_x, requires_grad=False)
    self.weight_y = nn.Parameter(data=kernel_y, requires_grad=False)

  def forward(self, x):
    grad_x = F.conv2d(x, self.weight_x)
    grad_y = F.conv2d(x, self.weight_y)
    gradient = torch.abs(grad_x) + torch.abs(grad_y)
    return gradient
</code></pre>
<p>Someone argued that the first one may lead to gradient explosion and the network can not be trained successfully. So I wonder which one should be used as a loss function? is there any better implementation?</p>

agaldran: <p>Hi Ford,</p>
<p>The kornia library has a full module dedicated to this kind of stuff. You can find nice implementations of differentiable operations like spatial gradients, sobel filters, etc that might suit your needs:</p>
<aside class="onebox allowlistedgeneric">
  <header class="source">
      <img src="https://kornia.readthedocs.io/en/latest/filters.html/_static/kornia_logo_mini.png" class="site-icon" width="15" height="15">
      <a href="https://kornia.readthedocs.io/en/latest/filters.html#kornia.filters.spatial_gradient" target="_blank" rel="noopener nofollow ugc">kornia.readthedocs.io</a>
  </header>
  <article class="onebox-body">
    <img src="" class="thumbnail" width="15" height="15">

<h3><a href="https://kornia.readthedocs.io/en/latest/filters.html#kornia.filters.spatial_gradient" target="_blank" rel="noopener nofollow ugc">kornia.filters — Kornia  documentation</a></h3>



  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>

<p>Cheers,</p>
<p>Adrian</p>

levi_WQ: <p>To compute the gradient of image (i.e. applying sobel filter), in the second code snippet, the line:<code>kernel_y = [[-1., 0., 1.], [-2., 0., 2.], [-1., 0., 1.]]</code> calculates partial derivative of x again, instead it should be corrected as <code>kernel_y = [[-1., -2., -1.], [0., 0., 0.], [1., 2., 1.]]</code>  to compute y derivate.</p>