Crops images based on entropy: leaving the most interesting part intact.
Best results achieved in combination with scaling: the cropping is then only used to square the image, cutting off the least interesting part. The trimming simply chops off te edge that is least interesting, and continues doing so, untill it reached the requested size.
Or add to you bundle file.
gem install smartcropper
With carrierwave, you use it in a custom
manipulate! block. For example, carrierwave in a Rails project:
def smart_crop_and_scale(width, height) manipulate! do |img| img = CropToelie.new(img) img = img.smart_crop_and_scale(width, height) img = yield(img) if block_given? img end end # Create different versions of your uploaded files: # A square and tiny thumbnail version :thumb do process :smart_crop_and_scale => [80, 80] end # A large version, only cropped version :preview do processs :crop => [200,400] end # A square version version :cover do process :smart_square end
With custom code, you simply create an instance of SmartCropper
image = Magick::ImageList("carice.jpg") SmartCropper.new(image).smart_square.write("carice_square.jpg") # Or, simpler SmartCropper.from_file("carice.jpg").smart_square.write("carice_square.jpg")
Smartcropper grabs a slice from both outer sides of the image. It compares the entropy of the slices and then removes the slice with the lowest entropy. More differentiating pixels (colors, shadows, depth) indicates a more interesting part of the image; a higher entropy.
It then repeats that for the top-and bottom
As you can see, entropy of a slice is not a perfect measurement of the "interestingness". Some slices have a high entropy, not because they contain the focus of the image, but some other artifact, like a tree, a logo or a lot of reflecting water.
Attempts to scan the image, rather then shaving it, have been made. But the result is not much better, yet the performance is hundreds times worse.
For now, shaving suffices. But I want to re-investigate the scanning-method, combined with some simple statistics to determine hotspots in the image. Then the "hotness" and size of these hotspots can be used to determine the boundries of the "interesting part".
The biggest hurdle, then, is to reduce memory-usage and amount of iterations; since the value of each pixel in an image must be loaded into memory and looped over, multiple times, you can image the performance for large-ish images.