Skip to content

Instantly share code, notes, and snippets.

@jcupitt
Created August 11, 2015 14:15
Show Gist options
  • Save jcupitt/c2792a9b22e4e2544147 to your computer and use it in GitHub Desktop.
Save jcupitt/c2792a9b22e4e2544147 to your computer and use it in GitHub Desktop.
smartcrop with libvips
#!/usr/bin/python
# smartcrop with libvips, based very roughly on
# http://stackoverflow.com/a/1517178/894763
import sys
from gi.repository import Vips
image = Vips.Image.new_from_file(sys.argv[1])
class Rect:
def __init__(self, left, top, width, height):
self.left = left
self.top = top
self.width = width
self.height = height
def intersect(self, other):
left = max(self.left, other.left)
right = min(self.left + self.width, other.left + other.width)
top = max(self.top, other.top)
bottom = min(self.top + self.height, other.top + other.height)
return Rect(left, top, right - left, bottom - top)
def union(self, other):
left = min(self.left, other.left)
right = max(self.left + self.width, other.left + other.width)
top = min(self.top, other.top)
bottom = max(self.top + self.height, other.top + other.height)
return Rect(left, top, right - left, bottom - top)
def crop(self, image):
return image.crop(self.left, self.top, self.width, self.height)
# how much off square is this image?
off_square = max(image.width, image.height) - min(image.width, image.height)
# trim the longer axis down in 10 steps, taking the lower-entropy end each time
step = int(off_square / 10.0)
while image.width != image.height:
off_square = max(image.width, image.height) - min(image.width, image.height)
if off_square < 2 * step:
this_step = off_square
else:
this_step = step
if image.width > image.height:
r1 = Rect(0, 0, this_step, image.height)
r2 = Rect(this_step, 0, image.width - 2 * this_step, image.height)
r3 = Rect(image.width - this_step, 0, this_step, image.height)
else:
r1 = Rect(0, 0, image.width, this_step)
r2 = Rect(0, this_step, image.width, image.height - 2 * this_step)
r3 = Rect(0, image.height - this_step, image.width, this_step)
ent1 = r1.crop(image).hist_find().hist_entropy()
ent3 = r3.crop(image).hist_find().hist_entropy()
if ent1 > ent3:
select = r2.union(r3)
else:
select = r1.union(r2)
image = select.crop(image)
image.write_to_file(sys.argv[2])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment