Finding list of 2D Patterns in a 2D tensor

I want to see if a dictionary of tensor of boolean pattern (e.g. {6x6 : freq}) exist in a larger boolean tensor (e.g. 3x256x256).

Then I want to update my dictionary, both pattern and frequency.

I was hoping that there was a pytorchi way of doing it, instead of having loops over it, or have an optimized loop for doing it.

As far as I know, torch.where works when we have a scalar value. I’m not sure how should I do, if I have a tensor of 6x6 instead of a value

I’m not sure I understand your question correctly…
Is it template matching?

h, w, kernel_size = 256, 256, 6
ks = kernel_size * kernel_size
tensor = torch.randn(3, h, w) > 0.5 
pattern = {
    tensor[0, 0:0+kernel_size, 4:4+kernel_size]: "A",
    tensor[1, 10:10+kernel_size, 3:3+kernel_size]: "B"
}

# Step 1, unfold the tensor
nh, nw = h - kernel_size + 1, w - kernel_size + 1
u_tensor = torch.nn.functional.unfold(tensor[None, ...].float(), kernel_size).clone()
u_tensor = u_tensor[0].bool().reshape(3, ks, -1)
u_tensor = u_tensor.permute(1, 0, 2).reshape(ks, -1)

# Step 2, search
for key, value in pattern.items():
    mask = u_tensor == key.view(-1, 1)
    indices = torch.where(mask.sum(dim=0) == ks)[0]
    
    # Step 3, parse indices
    indices_x = indices % nw 
    indices_y = (indices // nw) % nh 
    indices_c = indices // (nw * nh)
   
    # all works done.

    # Now Check the Result 
    for index_c, index_y, index_x in zip(indices_c, indices_y, indices_x):
        result = tensor[index_c, index_y:index_y+kernel_size, index_x:index+kernel_size]
        print((result == key).all())
1 Like

Thanks. No, I think I found the solution. It is convolution.

x = torch.tensor([[1., 0., 0.],
                      [0., 1., 0.],
                      [1., 0., 0.]])
pattern = torch.tensor([[1., 0.],
                            [0., 1.]])
img, mask = x[None, None], pattern[None, None]
M = F.conv2d(img, 1 - mask)
tensor([[[[0., 1.],
          [2., 0.]]]])
 M == mask.sum(dim> =(2,3)))
  tensor([[[[ True, False],
            [False, False]]]])

Actually, check this discuss, it shows that unfold is one way to implement conv2d. So, our methods are similar :wink:

Anyway, congratulations on finding a simpler way. :wink:

1 Like