#!/usr/bin/env python from __future__ import print_function from pathlib import Path import cv2 import numpy as np import os.path import sys def detect(path): img = cv2.imread(path) cascade = cv2.CascadeClassifier("detectors/haarcascade_frontalface_alt2.xml") rects = cascade.detectMultiScale(img, 1.3, 4, cv2.CASCADE_SCALE_IMAGE, (20,20)) if len(rects) == 0: return [], img rects[:, 2:] += rects[:, :2] return rects, img def box(rects, img): for x1, y1, x2, y2 in rects: cv2.rectangle(img, (x1, y1), (x2, y2), (127, 255, 0), 2) return img def smart_crop(rects, img): # Initialize height, width, _ = img.shape left, top = 0, 0 max_x, max_y, min_x, min_y = left, top, width, height # Find extremes of detected features if len(rects): print("Detected objects:", len(rects)) for x0, y0, x1, y1 in rects: min_x = min_x if min_x < x0 else x0 min_y = min_y if min_y < y0 else y0 max_x = max_x if max_x > x1 else x1 max_y = max_y if max_y > y1 else y1 # Focus in the center of detected features focus = 0.5 * (np.array([min_x, min_y]) + np.array([max_x, max_y])) crop_size = width if width < height else height x0, y0 = focus - crop_size / 2 x1, y1 = focus + crop_size / 2 # Move crop box towards center when it goes beyond x_vector, y_vector = 0, 0 if x0 < 0: x_vector = -x0 elif x1 > width: x_vector = width - x1 if y0 < 0: y_vector = -y0 elif y1 > height: y_vector = height - y1 x0 = int(x0 + x_vector) y0 = int(y0 + y_vector) return img[y0 : y0 + crop_size, x0 : x0 + crop_size] if __name__ == '__main__': file_name = sys.argv[1] print("Cropping:", file_name) rects, img = detect(file_name) thumb = cv2.resize(smart_crop(rects, img), (410, 410), fx=0, fy=0, interpolation=cv2.INTER_CUBIC) source = Path(file_name) cv2.imwrite(str(source.parent/"thumb"/source.name), thumb)