How can I batch-crop event photos automatically based on face position?

Asked 2/22/2015

2 views

2 answers

0

I have about 12,000 event photos, with one person in each image. I want to crop them automatically so the subject is better placed in the frame, rather than manually adjusting every file or applying the same crop to all images. Is there a workflow or tool that can detect the face/subject position and batch crop the images accordingly?

Originally by Photography Stack Exchange contributor. Source · Licensed CC BY-SA 4.0

Photography Stack Exchange contributor

11y ago

2 Answers

16

Here's a solution using python and opencv:

This will crop all the faces it finds in the jpeg photos in whatever folder you run it in, with the padding specified by the left, right, top, bottom variables:

import cv2
import sys
import glob 

cascPath = "haarcascade_frontalface_default.xml"

# Create the haar cascade
faceCascade = cv2.CascadeClassifier(cascPath)

files=glob.glob("*.jpg")   
for file in files:

    # Read the image
    image = cv2.imread(file)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Detect faces in the image
    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags = cv2.cv.CV_HAAR_SCALE_IMAGE
    )

    print "Found {0} faces!".format(len(faces))

    # Crop Padding
    left = 10
    right = 10
    top = 10
    bottom = 10

    # Draw a rectangle around the faces
    for (x, y, w, h) in faces:
        print x, y, w, h

        # Dubugging boxes
        # cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)


    image  = image[y-top:y+h+bottom, x-left:x+w+right]

    print "cropped_{1}{0}".format(str(file),str(x))
    cv2.imwrite("cropped_{1}_{0}".format(str(file),str(x)), image)

To Use

To use the above script you need python and opencv installed (just google how to install opencv for your platform).

Then save the above code as a .py file, "autocrop.py"or something, Then download and save this file and put it in the same directory as your images.

The script should find all the .jpg files in the folder and crop them based on the padding settings set in the python code.

Example:

With the above code set to 10 px padding to be dramatic, here's the source and result:

enter image description here

Result:

enter image description here

Here's the tutorial I shamelessly adapted:

https://realpython.com/blog/python/face-recognition-with-python/

That tutorial is far better at explaining everything than I am. Basically I just took that code and added in the little bit to batch-process stuff (instead of typing filenames) and then told it to crop and save instead of drawing a rectangle and displaying the picture.

Originally by user34574. Source · Licensed CC BY-SA 4.0

user34574

11y ago

0

AI Answer

Generated from our catalog & community — verify before relying on it.

Yes. A practical way to do this is to use face detection and crop each image based on the detected face position. The community suggested two workable approaches:

  1. Use Python with OpenCV: detect faces in each JPEG, then crop around the detected face with adjustable padding on the top, bottom, left, and right. This gives you control over how loose or tight the crop is.

  2. Use an existing batch tool such as autocrop for Python. It can scan a folder, detect faces, crop/resize images automatically, and place files where no face is found into a separate reject folder for manual review.

This is likely the most efficient approach for 12,000 images, but expect some misses or imperfect crops, especially with unusual poses, obstructed faces, or small subjects. You’ll probably still want to review the rejects and spot-check the output.

If your goal is rule-of-thirds placement rather than a centered headshot, choose or script a tool that lets you add asymmetric padding so the face sits off-center instead of in the middle.

UniqueBot

AI

11y ago

Your Answer