# How to change the kernel size in a custom image filter?

consider a custom image filter as

myfilter := {-1, 1} #[[1, 1]] + {0, 1} #[[1, 2]] + {1, 1} #[[1, 3]] +
{-1, 0} #[[2, 1]] + {0, 0} #[[2, 2]] + {1, 0} #[[2, 3]] +
{-1, -1} #[[3, 1]] + {0, -1} #[[3, 2]] + {1, -1} #[[3, 3]] &


I want to apply this to the following image (img)

The syntax for custom image filter is:

ImageFilter[myfilter, img, r]


The above filter currently works for r=3. How can I generalize this to work for any value of r?

Edit 1

Given the size of the kernel m I can generate the following Grid of relative positions.

Manipulate[Grid[n = 2 m + 1;
Table[{j - m - 1, m - i + 1}, {i, 1, n}, {j, 1, n}]], {m, 1, 5, 1}]


But I don't understand how to fit this into the filter to get the desired result.

Edit 2:

Based on the suggestions given in the comments I have modified my filters in the following way:

 vectorAbs :=
Norm[{-1, 1} #[[1, 1]] + {0, 1} #[[1, 2]] + {1, 1} #[[1, 3]] +
{-1, 0} #[[2, 1]] + {0, 0} #[[2, 2]] + {1, 0} #[[2, 3]] +
{-1, -1} #[[3, 1]] + {0, -1} #[[3, 2]] + {1, -1} #[[3, 3]]] &

vectorArg :=
ArcTan[{-1, 1} #[[1, 1]] + {0, 1} #[[1, 2]] + {1, 1} #[[1, 3]] +
{-1, 0} #[[2, 1]] + {0, 0} #[[2, 2]] + {1, 0} #[[2, 3]] +
{-1, -1} #[[3, 1]] + {0, -1} #[[3, 2]] + {1, -1} #[[3, 3]]] &


Now, I need to apply the filters on each channel as follows:

channels = ColorSeparate[img];
ColorCombine[
Table[ImageFilter[vectorAbs, channels[[i]], 1], {i, 1, 3}]]


This gives me

If I compare this result with the results using RidgeFilter, I get

I cannot thin the edges like this although it extracts a lot more feature boundaries.

If I use the vectorArg function, I get the two components like this

t = Table[
ColorSeparate@ImageFilter[vectorArg, channels[[i]], 1], {i, 1, 3}];
{ColorCombine[Transpose[t][[1]]], ColorCombine[Transpose[t][[2]]]}


• This filter doesn't work. It gives a pair of numbers instead of a single number. If you can generate the coefficients, then you can use Total. Your filter code can always detect the kernel size: it can see how big a block is passed to it. – Szabolcs Feb 19 '18 at 10:49
• Other minor things to note: 1. you don't need := here, you can use =. 2. this specific type of filter is better implemented using ImageConvolve. But I assumed your question was general and meant to apply to any filter. – Szabolcs Feb 19 '18 at 10:51
• @Szabolcs The filter is supposed to give me the vector sum of all the components. That's why there is a pair of numbers. However, I am sorry, I still don't get your point. Can you please explain this a bit more? – Majis Feb 19 '18 at 11:37
• I'm not sure what you mean by vector sum. A pixel value should be a number (for each image channel). Your function returns a pair of numbers. That's not valid for an image, and thus the example you showed fails with an error. – Szabolcs Feb 19 '18 at 14:05
• Other than this, what you are computing is basically a convolution. Why don't you use ImageConvolve? – Szabolcs Feb 19 '18 at 14:05