0
$\begingroup$

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)

enter image description here

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

enter image description here

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

enter image description here

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]]]}

enter image description here enter image description here

$\endgroup$
  • 1
    $\begingroup$ 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. $\endgroup$ – Szabolcs Feb 19 '18 at 10:49
  • 1
    $\begingroup$ 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. $\endgroup$ – Szabolcs Feb 19 '18 at 10:51
  • $\begingroup$ @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? $\endgroup$ – Majis Feb 19 '18 at 11:37
  • $\begingroup$ 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. $\endgroup$ – Szabolcs Feb 19 '18 at 14:05
  • $\begingroup$ Other than this, what you are computing is basically a convolution. Why don't you use ImageConvolve? $\endgroup$ – Szabolcs Feb 19 '18 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.