Skip to content

Instantly share code, notes, and snippets.

@kunik
Forked from jcupitt/trim.rb
Created November 4, 2015 01:23
Show Gist options
  • Save kunik/64f088fbadf0032b79e9 to your computer and use it in GitHub Desktop.
Save kunik/64f088fbadf0032b79e9 to your computer and use it in GitHub Desktop.
auto-crop in ruby-vips
#!/usr/bin/ruby
# An equivalent of ImageMagick's -trim in ruby-vips ... automatically remove
# "boring" image edges.
# We use .project to sum the rows and columns of a 0/255 mask image, the first
# non-zero row or column is the object edge. We make the mask image with an
# amount-differnt-from-background image plus a threshold.
require 'rubygems'
require 'vips'
im = VIPS::Image.new(ARGV[0])
class VIPS::Image
# split an image to a list of one-band images
def bandsplit
(0...bands).map {|i| extract_band(i)}
end
# a median filter
def median(size = 3)
rank(size, size, (size * size) / 2)
end
# get the value of a pixel as an array
def get_point(x, y)
extract_area(x, y, 1, 1).bandsplit.map {|i| i.avg}
end
end
# find the value of the pixel at (0, 0) ... we will search for all pixels
# significantly different from this
background = im.get_point(0, 0)
# we need to smooth the image, subtract the background from every pixel, take
# the absolute value of the difference, then threshold
# b = a.lin(c, d) calculates (b = a * c + d), we just want the d, so we must
# set the as to 1
ones = Array.new(background.length, 1)
mask = im.median.lin(ones, background.map {|x| x * -1}).abs.more(10)
# sum mask rows and columns, then search for the first non-zero sum in each
# direction
columns, rows = mask.project
left = columns.profile_h.min
right = columns.x_size - columns.fliphor.profile_h.min
top = rows.profile_v.min
bottom = rows.y_size - rows.flipver.profile_v.min
# and now crop the original image
im = im.extract_area(left, top, right - left, bottom - top)
im.write(ARGV[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment