Last active
September 14, 2017 14:15
-
-
Save dipu-bd/83ec6ca13651c312fada16afe44d0fa0 to your computer and use it in GitHub Desktop.
Generate thumbnail of given shape with smart cropping using opencv library.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2017 Sudipto Chandra <[email protected]> | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# The above copyright notice and this permission notice shall be included in all | |
# copies or substantial portions of the Software. | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
# SOFTWARE. | |
import os | |
import sys | |
from glob import glob | |
import cv2 | |
import numpy as np | |
################################################################################### | |
def get_thumb(img, width, height): | |
"""Gets the thumbnail from the image""" | |
row, col = img.shape[:2] | |
# rescale | |
m = get_scale(row, col, height, width) | |
size = int(col * m), int(row * m) | |
img = cv2.resize(img, size) | |
# autocrop | |
x, y = auto_crop(img, width, height) | |
crop = img[x:x+height, y:y+width] | |
return crop | |
# end def | |
def get_scale(x1, y1, x2, y2): | |
"""Gets the rescale amount from original(x1, y1) and target(x2, y2) size""" | |
if x1 < x2: | |
if y1 < y2: | |
if x1 < y1: | |
return x2 / x1 | |
else: | |
return y2 / y1 | |
# end if | |
else: | |
return x2 / x1 | |
# end if | |
else: | |
if y1 < y2: | |
return y2 / y1 | |
else: | |
if x1 < y1: | |
return x2 / x1 | |
else: | |
return y2 / y1 | |
# end if | |
# end if | |
# end if | |
# end def | |
def auto_crop(img, width, height): | |
"""Get crop area from image""" | |
row, col = img.shape[:2] | |
# get edge imagea | |
edges = cv2.Canny(img, 100, 200) | |
# use border | |
edges[:, :2] = 0 | |
edges[:, col-2:] = 0 | |
edges[:2, :] = 0 | |
edges[row-2:, :] = 0 | |
# horizontal crop | |
x = 0 | |
hor = np.sum(edges, axis=1) | |
for i in range(row - height): | |
if compare(hor, i, x, height): | |
x = i | |
# end if | |
# end for | |
# vertical crop | |
y = 0 | |
ver = np.sum(edges, axis=0) | |
for j in range(col - width): | |
if compare(ver, j, y, width): | |
y = j | |
# end if | |
# end for | |
return x, y | |
# end def | |
def compare(arr, pos1, pos2, siz): | |
x1 = arr[pos1] + arr[pos1 + siz] | |
x2 = arr[pos2] + arr[pos2 + siz] | |
y1 = np.sum(arr[pos1+1:pos1+siz-2]) | |
y2 = np.sum(arr[pos2+1:pos2+siz-2]) | |
#return x1 < x2 and y1 >= y2 | |
return y1 > y2 or (y1 == y2 and x1 < x2) | |
# end if | |
################################################################################### | |
def main(): | |
"""Main method""" | |
def show(file): | |
img = cv2.imread(file) | |
if img is not None: | |
img = get_thumb(img, width, height) | |
cv2.imshow('{} @ {} x {}'.format(file, width, height), img) | |
cv2.waitKey() | |
# end if | |
# end def | |
try: | |
file = os.path.abspath(sys.argv[1]) | |
width = int(sys.argv[2]) | |
height = int(sys.argv[3]) | |
if os.path.isdir(file): | |
for f in sorted(glob(os.path.join(file, '*.*'))): | |
show(f) | |
# end for | |
else: | |
show(file) | |
# end if | |
except IndexError: | |
print_help() | |
except: | |
print_help() | |
raise | |
# end try | |
# end def | |
def print_help(): | |
"""Shows help""" | |
print('Extracts thumbnail from an image.', end='\n\n') | |
print('$> python thumb.py <image_path> <width> <height>', end='\n\n') | |
print(' image_path The image file or some directory containing images') | |
print(' width Thumbnail width') | |
print(' height Thumbnail height') | |
print() | |
# end def | |
if __name__ == '__main__': | |
main() | |
# end if |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment