Upload 7 files
Browse files- extract_faces.py +75 -0
- install.bat +33 -0
- resizer_v4.py +154 -0
- run_extract_faces_CPU.bat +10 -0
- run_extract_faces_GPU.bat +10 -0
- run_resizer_CPU.bat +10 -0
- run_resizer_GPU.bat +10 -0
extract_faces.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from PIL import Image
|
| 3 |
+
from retinaface import RetinaFace
|
| 4 |
+
from concurrent.futures import ProcessPoolExecutor
|
| 5 |
+
|
| 6 |
+
Image.MAX_IMAGE_PIXELS = 200000000 # Allow images up to 200 million pixels
|
| 7 |
+
|
| 8 |
+
DATA = [
|
| 9 |
+
((512, 512), r"G:\man dataset\man_4502_imgs_raw"),
|
| 10 |
+
((1024, 1024), r"G:\man dataset\man_4502_imgs_raw")
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
NUM_THREADS = 1 # Modify this for the desired number of threads
|
| 14 |
+
OUTPUT_ROOT = r"H:\man dataset\resize_faces" # Root folder to save resized face images
|
| 15 |
+
|
| 16 |
+
## change resize enabled to resize
|
| 17 |
+
def resize_face(args, resize_enabled=False):
|
| 18 |
+
try:
|
| 19 |
+
input_path, resolution, output_root = args
|
| 20 |
+
except ValueError as e:
|
| 21 |
+
print(f"Error unpacking arguments: {e}")
|
| 22 |
+
return
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
image = Image.open(input_path)
|
| 26 |
+
except Exception as e:
|
| 27 |
+
print(f"Error loading image: {e}")
|
| 28 |
+
return
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
# Detect faces
|
| 32 |
+
faces = RetinaFace.detect_faces(input_path)
|
| 33 |
+
|
| 34 |
+
if not faces:
|
| 35 |
+
print(f"No face detected in {input_path}")
|
| 36 |
+
return
|
| 37 |
+
|
| 38 |
+
# Assuming we take the first detected face
|
| 39 |
+
face = next(iter(faces.values()))
|
| 40 |
+
x, y, x2, y2 = face['facial_area']
|
| 41 |
+
face_image = image.crop((x, y, x2, y2))
|
| 42 |
+
|
| 43 |
+
if resize_enabled:
|
| 44 |
+
# Resize the cropped face only if resizing is enabled
|
| 45 |
+
face_image = face_image.resize(resolution, Image.LANCZOS)
|
| 46 |
+
except Exception as e:
|
| 47 |
+
print(f"Error in face detection or resizing: {e}")
|
| 48 |
+
return
|
| 49 |
+
|
| 50 |
+
try:
|
| 51 |
+
output_folder = os.path.join(output_root, f"{resolution[0]}x{resolution[1]}" if resize_enabled else "no_resize")
|
| 52 |
+
if not os.path.exists(output_folder):
|
| 53 |
+
os.makedirs(output_folder)
|
| 54 |
+
|
| 55 |
+
output_path = os.path.join(output_folder, os.path.basename(input_path))
|
| 56 |
+
face_image.save(output_path, quality=100)
|
| 57 |
+
except Exception as e:
|
| 58 |
+
print(f"Error saving image: {e}")
|
| 59 |
+
|
| 60 |
+
def process_folder(input_folder, resolution, resize_enabled=False):
|
| 61 |
+
image_paths = [os.path.join(input_folder, fname) for fname in os.listdir(input_folder) if fname.lower().endswith(('png', 'jpg', 'jpeg'))]
|
| 62 |
+
|
| 63 |
+
total_images = len(image_paths)
|
| 64 |
+
processed_count = 0
|
| 65 |
+
|
| 66 |
+
with ProcessPoolExecutor(max_workers=NUM_THREADS) as executor:
|
| 67 |
+
for _ in executor.map(resize_face, [(path, resolution, OUTPUT_ROOT) for path in image_paths], [resize_enabled] * len(image_paths)):
|
| 68 |
+
processed_count += 1
|
| 69 |
+
print(f"Processed {processed_count}/{total_images} images for resolution {resolution[0]}x{resolution[1]} (Resize: {'Enabled' if resize_enabled else 'Disabled'})...")
|
| 70 |
+
|
| 71 |
+
if __name__ == "__main__":
|
| 72 |
+
resize_enabled = False # Change this to True if resizing is needed
|
| 73 |
+
for resolution, folder in DATA:
|
| 74 |
+
process_folder(folder, resolution, resize_enabled)
|
| 75 |
+
print("Processing complete!")
|
install.bat
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
|
| 3 |
+
python.exe -m pip install --upgrade pip
|
| 4 |
+
|
| 5 |
+
REM Create virtual environment folder
|
| 6 |
+
echo composing venv
|
| 7 |
+
IF NOT EXIST venv (
|
| 8 |
+
python -m venv venv
|
| 9 |
+
) ELSE (
|
| 10 |
+
echo venv folder already exists, skipping making new venv...
|
| 11 |
+
)
|
| 12 |
+
call .\venv\Scripts\activate.bat
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
pip3 install torch==2.0.1 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
|
| 17 |
+
|
| 18 |
+
pip install tensorflow==2.10
|
| 19 |
+
|
| 20 |
+
pip install transformers
|
| 21 |
+
|
| 22 |
+
pip install Pillow
|
| 23 |
+
|
| 24 |
+
pip install retina-face
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
REM Show completion message
|
| 30 |
+
echo Virtual environment made and installed properly
|
| 31 |
+
|
| 32 |
+
REM Pause to keep the command prompt open
|
| 33 |
+
pause
|
resizer_v4.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import time
|
| 3 |
+
from PIL import Image
|
| 4 |
+
from retinaface import RetinaFace
|
| 5 |
+
from concurrent.futures import ProcessPoolExecutor
|
| 6 |
+
|
| 7 |
+
Image.MAX_IMAGE_PIXELS = 200000000 # Allow images up to 200 million pixels
|
| 8 |
+
|
| 9 |
+
DATA = [
|
| 10 |
+
((768,1368), r"F:\woman dataset\768x1368"),
|
| 11 |
+
((1216, 832), r"F:\woman dataset\1216x832")
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
DATA = [
|
| 15 |
+
((512, 512), r"H:\woman dataset\1536x1536"),
|
| 16 |
+
((768, 768), r"H:\woman dataset\1536x1536"),
|
| 17 |
+
((1024, 1024), r"H:\woman dataset\1536x1536"),
|
| 18 |
+
((1536, 1536), r"H:\woman dataset\1536x1536"),
|
| 19 |
+
((1280, 1536), r"H:\woman dataset\1280x1536"),
|
| 20 |
+
((1536, 1280), r"H:\woman dataset\1536x1280"),
|
| 21 |
+
((1024, 1536), r"H:\woman dataset\1024x1536"),
|
| 22 |
+
((1536, 1024), r"H:\woman dataset\1536x1024"),
|
| 23 |
+
((512, 768), r"H:\woman dataset\1024x1536"),
|
| 24 |
+
((768, 512), r"H:\woman dataset\1536x1024"),
|
| 25 |
+
((768, 1024), r"H:\woman dataset\768x1024"),
|
| 26 |
+
((1024, 768), r"H:\woman dataset\1024x768"),
|
| 27 |
+
((1024, 1280), r"H:\woman dataset\1024x1280"),
|
| 28 |
+
((1280, 1024), r"H:\woman dataset\1280x1024"),
|
| 29 |
+
((640,1536), r"H:\woman dataset\640x1536"),
|
| 30 |
+
((1536, 640), r"H:\woman dataset\1536x640"),
|
| 31 |
+
((768,1344), r"H:\woman dataset\768x1344"),
|
| 32 |
+
((1344, 768), r"H:\woman dataset\1344x768"),
|
| 33 |
+
((768,1368), r"H:\woman dataset\768x1368"),
|
| 34 |
+
((1368, 768), r"H:\woman dataset\1368x768"),
|
| 35 |
+
((832,1216), r"H:\woman dataset\832x1216"),
|
| 36 |
+
((1216, 832), r"H:\woman dataset\1216x832"),
|
| 37 |
+
((896,1152), r"H:\woman dataset\896x1152"),
|
| 38 |
+
((1152, 896), r"H:\woman dataset\1152x896")
|
| 39 |
+
]
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
NUM_THREADS = 1 # Modify this for the desired number of threads
|
| 44 |
+
OUTPUT_ROOT = r"G:\woman dataset\fixed_faces_png" # Root folder to save resized images
|
| 45 |
+
Save_PNG = False # Options are True and False
|
| 46 |
+
LOG_FILE = "face_detection_failures.txt" # File to log images where faces can't be detected
|
| 47 |
+
|
| 48 |
+
def resize_image(args):
|
| 49 |
+
start_time = time.time() # Start timing
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
input_path, resolution, output_root, save_as_png = args
|
| 53 |
+
except ValueError as e:
|
| 54 |
+
print(f"Error unpacking arguments: {e}")
|
| 55 |
+
return None
|
| 56 |
+
|
| 57 |
+
try:
|
| 58 |
+
# Load the image
|
| 59 |
+
image = Image.open(input_path)
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print(f"Error loading image: {e}")
|
| 62 |
+
return None
|
| 63 |
+
|
| 64 |
+
face_detected = True
|
| 65 |
+
face_locations = None
|
| 66 |
+
|
| 67 |
+
try:
|
| 68 |
+
# Get face locations using RetinaFace
|
| 69 |
+
faces = RetinaFace.detect_faces(input_path)
|
| 70 |
+
|
| 71 |
+
if not faces or 'face_1' not in faces:
|
| 72 |
+
face_detected = False
|
| 73 |
+
with open(LOG_FILE, 'a') as log:
|
| 74 |
+
log.write(f"Face not detected: {input_path}\n")
|
| 75 |
+
else:
|
| 76 |
+
face = faces['face_1']
|
| 77 |
+
x, y, x2, y2 = face['facial_area']
|
| 78 |
+
face_locations = [(y, x2, y2, x)] # Adjust format to match face_recognition
|
| 79 |
+
except Exception as e:
|
| 80 |
+
print(f"Error detecting faces: {e}")
|
| 81 |
+
face_detected = False
|
| 82 |
+
|
| 83 |
+
# Proceed with cropping and resizing
|
| 84 |
+
try:
|
| 85 |
+
desired_aspect_ratio = resolution[0] / resolution[1]
|
| 86 |
+
image_aspect_ratio = image.width / image.height
|
| 87 |
+
|
| 88 |
+
# Calculate crop dimensions
|
| 89 |
+
if image_aspect_ratio > desired_aspect_ratio:
|
| 90 |
+
new_width = int(image.height * desired_aspect_ratio)
|
| 91 |
+
new_height = image.height
|
| 92 |
+
else:
|
| 93 |
+
new_width = image.width
|
| 94 |
+
new_height = int(image.width / desired_aspect_ratio)
|
| 95 |
+
|
| 96 |
+
# Default centering
|
| 97 |
+
left = (image.width - new_width) / 2
|
| 98 |
+
top = (image.height - new_height) / 2
|
| 99 |
+
right = (image.width + new_width) / 2
|
| 100 |
+
bottom = (image.height + new_height) / 2
|
| 101 |
+
|
| 102 |
+
# Adjust for face center if a face is detected
|
| 103 |
+
if face_detected and face_locations:
|
| 104 |
+
face_top, face_right, face_bottom, face_left = face_locations[0]
|
| 105 |
+
face_center_x = (face_left + face_right) // 2
|
| 106 |
+
face_center_y = (face_top + face_bottom) // 2
|
| 107 |
+
|
| 108 |
+
left = min(max(0, face_center_x - new_width // 2), image.width - new_width)
|
| 109 |
+
top = min(max(0, face_center_y - new_height // 2), image.height - new_height)
|
| 110 |
+
right = left + new_width
|
| 111 |
+
bottom = top + new_height
|
| 112 |
+
|
| 113 |
+
image = image.crop((left, top, right, bottom))
|
| 114 |
+
|
| 115 |
+
# Resize image with best resampling filter (LANCZOS)
|
| 116 |
+
image = image.resize(resolution, Image.LANCZOS)
|
| 117 |
+
|
| 118 |
+
output_folder = os.path.join(output_root, f"{resolution[0]}x{resolution[1]}")
|
| 119 |
+
if not os.path.exists(output_folder):
|
| 120 |
+
os.makedirs(output_folder)
|
| 121 |
+
|
| 122 |
+
output_path = os.path.join(output_folder, os.path.basename(input_path))
|
| 123 |
+
if save_as_png:
|
| 124 |
+
output_path = os.path.splitext(output_path)[0] + '.png'
|
| 125 |
+
image.save(output_path, format='PNG')
|
| 126 |
+
else:
|
| 127 |
+
image.save(output_path, quality=100)
|
| 128 |
+
|
| 129 |
+
except Exception as e:
|
| 130 |
+
print(f"Error processing or saving image: {e}")
|
| 131 |
+
return None
|
| 132 |
+
|
| 133 |
+
end_time = time.time() # End timing
|
| 134 |
+
return end_time - start_time # Return processing time
|
| 135 |
+
|
| 136 |
+
def process_folder(input_folder, resolution, save_as_png):
|
| 137 |
+
image_paths = [os.path.join(input_folder, fname) for fname in os.listdir(input_folder) if fname.lower().endswith(('png', 'jpg', 'jpeg'))]
|
| 138 |
+
|
| 139 |
+
total_images = len(image_paths)
|
| 140 |
+
processed_count = 0
|
| 141 |
+
total_time = 0 # Total time for processing images
|
| 142 |
+
|
| 143 |
+
with ProcessPoolExecutor(max_workers=NUM_THREADS) as executor:
|
| 144 |
+
for processing_time in executor.map(resize_image, [(path, resolution, OUTPUT_ROOT, save_as_png) for path in image_paths]):
|
| 145 |
+
processed_count += 1
|
| 146 |
+
if processing_time is not None:
|
| 147 |
+
total_time += processing_time
|
| 148 |
+
average_time = total_time / processed_count * 1000 # Convert to milliseconds
|
| 149 |
+
print(f"Processed {processed_count}/{total_images} images for resolution {resolution[0]}x{resolution[1]}... Average processing time per image: {average_time:.2f} ms")
|
| 150 |
+
|
| 151 |
+
if __name__ == "__main__":
|
| 152 |
+
for resolution, folder in DATA:
|
| 153 |
+
process_folder(folder, resolution, Save_PNG)
|
| 154 |
+
print("Processing complete!")
|
run_extract_faces_CPU.bat
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
|
| 3 |
+
echo don't forget to run install bat and make sure that you have changed the paths in resize_faces.py file
|
| 4 |
+
echo moreover set your thread count according to your CPU
|
| 5 |
+
call .\venv\Scripts\activate.bat
|
| 6 |
+
|
| 7 |
+
set CUDA_VISIBLE_DEVICES=124121
|
| 8 |
+
python extract_faces.py
|
| 9 |
+
|
| 10 |
+
pause
|
run_extract_faces_GPU.bat
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
|
| 3 |
+
echo don't forget to run install bat and make sure that you have changed the paths in resize_faces.py file
|
| 4 |
+
echo moreover set your thread count according to your CPU
|
| 5 |
+
call .\venv\Scripts\activate.bat
|
| 6 |
+
|
| 7 |
+
set CUDA_VISIBLE_DEVICES=0
|
| 8 |
+
python extract_faces.py
|
| 9 |
+
|
| 10 |
+
pause
|
run_resizer_CPU.bat
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
|
| 3 |
+
echo don't forget to run install bat and make sure that you have changed the paths in resizer_v4.py file
|
| 4 |
+
echo moreover set your thread count according to your CPU
|
| 5 |
+
call .\venv\Scripts\activate.bat
|
| 6 |
+
|
| 7 |
+
set CUDA_VISIBLE_DEVICES=1231412
|
| 8 |
+
python resizer_v4.py
|
| 9 |
+
|
| 10 |
+
pause
|
run_resizer_GPU.bat
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
|
| 3 |
+
echo don't forget to run install bat and make sure that you have changed the paths in resizer_v4.py file
|
| 4 |
+
echo moreover set your thread count according to your CPU
|
| 5 |
+
call .\venv\Scripts\activate.bat
|
| 6 |
+
|
| 7 |
+
set CUDA_VISIBLE_DEVICES=0
|
| 8 |
+
python resizer_v4.py
|
| 9 |
+
|
| 10 |
+
pause
|