face-recognition / face_detection.py
bytchew's picture
Update face_detection.py
ae72117 verified
from typing import List
import face_recognition
from PIL import Image
from os import path as p
import os
import numpy as np
# Main method utilized to crop the group photos into various individual person photos to feed into the model
def getCroppedImages(image: Image.Image, cap = -1):
"""Takes a PIL image, and returns a list of PIL images with the cropped faces"""
image = image.convert("RGB")
face_locations = face_recognition.face_locations(np.array(image))
face_locations_n = []
outputs = []
num = 0
# Adjust dimensions of cropping to include more context
width, height = image.size # Get image dimensions
for f in face_locations:
if cap != -1 and num >= cap:
break
# Original coordinates: (top, right, bottom, left)
top, right, bottom, left = f
# Center of the face rectangle
center_x = (left + right) / 2
center_y = (top + bottom) / 2
# Expanded dimensions
box_width = (right - left) * 1.6
box_height = (bottom - top) * 1.6
new_left = int(center_x - box_width / 2)
new_right = int(center_x + box_width / 2)
new_top = int(center_y - box_height / 2)
new_bottom = int(center_y + box_height / 2)
# Clamp to image boundaries
new_left = max(0, new_left)
new_right = min(width, new_right)
new_top = max(0, new_top)
new_bottom = min(height, new_bottom)
# Crop the image with the new coordinates
c = (new_left, new_top, new_right, new_bottom)
outputs.append(image.crop(c))
face_locations_n.append(c)
num += 1
# Return face_locations_n, outputs
return face_locations_n, outputs
# These following methods crop images but are not utilized in our app
# def getFaceLocationsAndFiles(input_path: str, output_dir: str, output_name: str,):
# """
# input_path: local or absolute path to the input image\n
# output_dir: folder (local or absolute path) to save the output image to\n
# output_name: name for the new image (do not include extension)\n
# returns: list of face locations and list of paths to the cropped face images
# """
# locs, imgs = getCroppedImages(Image.open(input_path))
# output_paths = []
# num = 0
# for i in imgs:
# path = p.join(output_dir, f"{output_name}_{num}.png")
# i.save(path)
# output_paths.append(p.abspath(path))
# num += 1
# return locs, output_paths
# def createCroppedSetFromImage(input_path: str, output_dir: str, output_name: str, cap = -1):
# """
# input_path: local or absolute path to the input image\n
# output_dir: folder (local or absolute path) to save the output image to\n
# output_name: name for the new image (do not include extension)\n
# cap: set to -1 to process all faces detected, otherwise will limit faces to value\n
# returns: list of absolute paths to the images
# """
# imgs = getCroppedImages(Image.open(input_path))[1]
# num = 0
# for i in imgs:
# path = p.join(output_dir, f"{output_name}_{num}.png")
# i.save(path)
# num += 1
# def createCroppedSets(input_path: str, output_path: str):
# """
# Iterates through subdirectories in the input directory, making a duplicate of it in the output directory.
# Then iterates through all images in the subdirectory, cropping each face and saving it to the output directory.
# For example for params "input" and "output", input/Dwayne Johnson/img.png will be cropped and
# saved to output/Dwayne Johnson/0_0.png (repeated for all folder and the images they contain)
# WARNING: IF A DIRECTORY WITH THE SAME NAME AS THE OUTPUT DIRECTORY, IT WILL BE DELETED
# """
# # delete previous folder so there's no conflicts
# if(p.exists(output_path)):
# shutil.rmtree(output_path)
# os.mkdir(output_path)
# # iterate through all subdirectories in input directory
# for dir in [name for name in os.listdir(input_path) if p.isdir(p.join(input_path, name))]:
# sub_out = p.join(output_path, dir)
# sub_in = p.join(input_path, dir)
# os.mkdir(sub_out)
# n = 0
# # iterate through all files in subdirectory
# for img in [name for name in os.listdir(sub_in) if p.isfile(p.join(sub_in, name))]:
# createCroppedSetFromImage(p.join(sub_in, img), sub_out, n, 1)
# n += 1