0

I want to do a thing like this:

enter image description here

http://reference.wolfram.com/language/ref/MaxFilter.html

Lets say my image has one channel (is grayscale).

Nakilon
  • 34,866
  • 14
  • 107
  • 142

2 Answers2

0

Here is how I did it with PI * R * R convolutions.

R = 2
D = R + R + 1
CIRCLE = Vips::Image.black(D, D).draw_circle(1, R, R, R, fill: true).to_a

new_image = image
D.times do |i|
  D.times do |j|
    next unless CIRCLE[i][j] == [1]
    t = image.conv Vips::Image.new_from_array Array.new(D){ [0]*D }.tap{ |t| t[i][j] = 1 }
    new_image = (new_image > t).ifthenelse(new_image, t)
  end
end

return new_image
Nakilon
  • 34,866
  • 14
  • 107
  • 142
0

If you don't mind a square window, you can do this with a rank filter:

result = image.rank w, h, w * h - 1

http://jcupitt.github.io/libvips/API/current/libvips-morphology.html#vips-rank

http://www.rubydoc.info/gems/ruby-vips/Vips/Image#rank-instance_method

Where w and h are the width and height of the window.

Of course, max/min are separable, so you could also write this as:

result = image.rank(w, 1, w - 1).rank(1, h, h - 1)

which would be much faster for a large radius.

jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • Window shape is of course important. Though this is interesting method. Maybe it's possible to express a circle of radius 5 as two overlapping rectangles of 3x5 and 5x3 ans somehow combine results. Not sure about larger radiuses but this can be faster than my method. – Nakilon Nov 26 '17 at 08:21
  • That's a clever idea. How large an R do you need to work for? – jcupitt Nov 26 '17 at 11:21