Filtering image in pytorch

Frida: <p>Hi<br>
Does anyone know how to set not learned filter as part of the training in pytorch? Specifically, I would like to have a filter that preserve high freq content. Thanks!</p>

JuanFMontesinos: <p>You just need to use the conv2d functional passing your own filter<br>
<a href="https://pytorch.org/docs/stable/nn.functional.html?highlight=conv2d#torch.nn.functional.conv2d" class="onebox" target="_blank" rel="nofollow noopener">https://pytorch.org/docs/stable/nn.functional.html?highlight=conv2d#torch.nn.functional.conv2d</a></p>
<pre><code class="lang-auto">torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)
</code></pre>
<p>Remember pytorch uses crosscorrelation.</p>

Frida: <p>Thanks! And it won’t learn its parameters?<br>
What about back-propagating through it?</p>

JuanFMontesinos: <p>It will consider the kernel in order to backprop of course. But, as it is a fixed tensor it won’t learn.<br>
The functional is just a function which applies the convolution. The nn.Module is a class which contains learnable parameters. Those are passed to the optimizer, hence, learned.</p>
<p>Note: Remember that you have to define the filter as a tensor, NOT as a nn.Parameter. Otherwise it will be learned too. <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

edgarriba: <p>take a look at <code>kornia.filters</code> module<br>
<a href="https://kornia.readthedocs.io/en/latest/filters.html" class="onebox" target="_blank" rel="nofollow noopener">https://kornia.readthedocs.io/en/latest/filters.html</a></p>

nima_pw: <p>Dear <a class="mention" href="/u/juanfmontesinos">@JuanFMontesinos</a><br>
I want to apply this high-pass filter to my images:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/f/9/f91b27030416141fcdf4e5737c25bf21496b2509.png" alt="image" data-base62-sha1="zxH3XvFV7f52z3KCLHcyuskvVIR" width="401" height="162"></p>
<p>My model is defined as below:</p>
<pre><code class="lang-auto">class CNN(nn.Module):
    
    def __init__(self):
        super(CNN, self).__init__()
        
        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 96, kernel_size=7, stride=1 , padding=3),
            nn.BatchNorm2d(96),
            nn.ReLU(),
            nn.MaxPool2d(2)
.
.
.
</code></pre>
<p>Could you please help me with how to do that? (not learned filter)</p>
<p>Can I apply the filter out of the model? for example, in dataloader?<br>
Thank you I found the answer:</p>
<p>======<br>
[<a href="https://discuss.pytorch.org/t/apply-filter-as-a-part-of-preprocessing/115329" class="inline-onebox">Apply Filter as a part of preprocessing</a>]</p>

brogos: <p>I tried this way and it’s working:</p>
<pre><code class="lang-python">import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn.functional as F
from skimage import data

# loads gray-level camera image.
image = data.camera()
# reshaping image because it needs to have (batches, channels, height, width)
image = image.reshape(1, 1, image.shape[0], image.shape[1])
# Converting to Tensor
t_image = torch.as_tensor(image.astype(np.float32))
# Creating a 4x4 mean filter. It needs to have (batches, channels, filter height, filter width)
t_filter = torch.as_tensor(np.full((1, 1, 4, 4), 1.0 / 16.0, dtype=np.float32))
# Using F.conv2d to apply the filter
f_image = F.conv2d(t_image, t_filter)

plt.imshow(f_image.numpy().squeeze())
plt.show()
</code></pre>

JuanFMontesinos: <p>Hi,<br>
A layer is usually composed by a functional (a function) + weights. Here you just need to define your weights manually and call the functional. In pseudo code it’d be:</p>
<pre><code class="lang-auto">class CNN(nn.Module):
    
    def __init__(self):
        super(CNN, self).__init__()
        
        self.register_buffer('custom_conv_weight', KERNEL, persistent=True)
        self.post_conv= nn.Sequential(
            nn.BatchNorm2d(96),
            nn.ReLU(),
            nn.MaxPool2d(2))
def forward:
      x = torch.nn.functional.conv2d(INPUT,self.custom_conv_weight,stride=1 , padding=3)
      x = self.post_conv(x)
....
</code></pre>
<p>Here note that your kernel is 1d and your input has 3 channels, thus, you need to expand repeat the kernel 3 times to run the same filter for all the image channels.</p>