File size: 4,773 Bytes
9754b95 babdf76 9754b95 4de751c 9754b95 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import os
import time
from PIL import Image
from retinaface import RetinaFace
from concurrent.futures import ProcessPoolExecutor
Image.MAX_IMAGE_PIXELS = 200000000 # Allow images up to 200 million pixels
DATA = [
((768, 768), r"/kaggle/input/samikk"),
((1024, 1024), r"/kaggle/input/samikk"),
]
NUM_THREADS = 1 # Modify this for the desired number of threads
OUTPUT_ROOT = r"/kaggle/working/outputs" # Root folder to save resized images
Save_PNG = False # Options are True and False
LOG_FILE = "face_detection_failures.txt" # File to log images where faces can't be detected
def resize_image(args):
start_time = time.time() # Start timing
try:
input_path, resolution, output_root, save_as_png = args
except ValueError as e:
print(f"Error unpacking arguments: {e}")
return None
try:
# Load the image
image = Image.open(input_path)
except Exception as e:
print(f"Error loading image: {e}")
return None
face_detected = True
face_locations = None
try:
# Get face locations using RetinaFace
faces = RetinaFace.detect_faces(input_path)
if not faces or 'face_1' not in faces:
face_detected = False
with open(LOG_FILE, 'a') as log:
log.write(f"Face not detected: {input_path}\n")
else:
face = faces['face_1']
x, y, x2, y2 = face['facial_area']
face_locations = [(y, x2, y2, x)] # Adjust format to match face_recognition
except Exception as e:
print(f"Error detecting faces: {e}")
face_detected = False
# Proceed with cropping and resizing
try:
desired_aspect_ratio = resolution[0] / resolution[1]
image_aspect_ratio = image.width / image.height
# Calculate crop dimensions
if image_aspect_ratio > desired_aspect_ratio:
new_width = int(image.height * desired_aspect_ratio)
new_height = image.height
else:
new_width = image.width
new_height = int(image.width / desired_aspect_ratio)
# Default centering
left = (image.width - new_width) / 2
top = (image.height - new_height) / 2
right = (image.width + new_width) / 2
bottom = (image.height + new_height) / 2
# Adjust for face center if a face is detected
if face_detected and face_locations:
face_top, face_right, face_bottom, face_left = face_locations[0]
face_center_x = (face_left + face_right) // 2
face_center_y = (face_top + face_bottom) // 2
left = min(max(0, face_center_x - new_width // 2), image.width - new_width)
top = min(max(0, face_center_y - new_height // 2), image.height - new_height)
right = left + new_width
bottom = top + new_height
image = image.crop((left, top, right, bottom))
# Resize image with best resampling filter (LANCZOS)
image = image.resize(resolution, Image.LANCZOS)
output_folder = os.path.join(output_root, f"{resolution[0]}x{resolution[1]}")
if not os.path.exists(output_folder):
os.makedirs(output_folder)
output_path = os.path.join(output_folder, os.path.basename(input_path))
if save_as_png:
output_path = os.path.splitext(output_path)[0] + '.png'
image.save(output_path, format='PNG')
else:
image.save(output_path, quality=100)
except Exception as e:
print(f"Error processing or saving image: {e}")
return None
end_time = time.time() # End timing
return end_time - start_time # Return processing time
def process_folder(input_folder, resolution, save_as_png):
image_paths = [os.path.join(input_folder, fname) for fname in os.listdir(input_folder) if fname.lower().endswith(('png', 'jpg', 'jpeg'))]
total_images = len(image_paths)
processed_count = 0
total_time = 0 # Total time for processing images
with ProcessPoolExecutor(max_workers=NUM_THREADS) as executor:
for processing_time in executor.map(resize_image, [(path, resolution, OUTPUT_ROOT, save_as_png) for path in image_paths]):
processed_count += 1
if processing_time is not None:
total_time += processing_time
average_time = total_time / processed_count * 1000 # Convert to milliseconds
print(f"Processed {processed_count}/{total_images} images for resolution {resolution[0]}x{resolution[1]}... Average processing time per image: {average_time:.2f} ms")
if __name__ == "__main__":
for resolution, folder in DATA:
process_folder(folder, resolution, Save_PNG)
print("Processing complete!")
|