import os import cv2 from pathlib import Path # ========================= # CONFIG # ========================= INPUT_FOLDER = "../Celebrity" # root folder with subfolders OUTPUT_FOLDER = "../Celebrity_croped" # output folder # extra padding around detected face PADDING_PERCENT = 0.35 # final output image size OUTPUT_SIZE = 224 # supported image extensions IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".webp"] # ========================= # LOAD FACE DETECTOR # ========================= face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) # ========================= # HELPERS # ========================= def make_square_crop(img, x, y, w, h, padding=0.3): """ Create square crop around face with padding. """ img_h, img_w = img.shape[:2] # face center cx = x + w // 2 cy = y + h // 2 # make square size side = int(max(w, h) * (1 + padding * 2)) x1 = max(cx - side // 2, 0) y1 = max(cy - side // 2, 0) x2 = min(x1 + side, img_w) y2 = min(y1 + side, img_h) # adjust if crop hits boundaries crop_w = x2 - x1 crop_h = y2 - y1 side = min(crop_w, crop_h) x2 = x1 + side y2 = y1 + side return img[y1:y2, x1:x2] def detect_largest_face(img): """ Detect largest face in image. """ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(50, 50) ) if len(faces) == 0: return None # choose largest face largest = max(faces, key=lambda f: f[2] * f[3]) return largest def process_image(input_path, output_path): """ Crop face and save. """ img = cv2.imread(str(input_path)) if img is None: print(f"Failed to read: {input_path}") return face = detect_largest_face(img) if face is None: print(f"No face detected: {input_path}") return x, y, w, h = face crop = make_square_crop( img, x, y, w, h, padding=PADDING_PERCENT ) crop = cv2.resize(crop, (OUTPUT_SIZE, OUTPUT_SIZE)) output_path.parent.mkdir(parents=True, exist_ok=True) cv2.imwrite(str(output_path), crop) print(f"Saved: {output_path}") # ========================= # MAIN # ========================= def main(): input_root = Path(INPUT_FOLDER) output_root = Path(OUTPUT_FOLDER) image_files = [] for ext in IMAGE_EXTENSIONS: image_files.extend(input_root.rglob(f"*{ext}")) image_files.extend(input_root.rglob(f"*{ext.upper()}")) print(f"Found {len(image_files)} images") for img_path in image_files: relative_path = img_path.relative_to(input_root) output_path = output_root / relative_path process_image(img_path, output_path) print("\nDone.") if __name__ == "__main__": main()