Browse Source

inital commit

master
cailean 1 month ago
commit
213321e0fc
  1. 2
      .gitignore
  2. 0
      README.md
  3. 167
      app.py
  4. 117
      process_video.py
  5. 74
      requirements.txt
  6. 90675
      sv_embeddings.json

2
.gitignore

@ -0,0 +1,2 @@
/main_dataset/
/dataset/

0
README.md

167
app.py

@ -0,0 +1,167 @@
from deepface import DeepFace
import os
import glob
import json
import numpy as np
baseFolderPath = "main_dataset"
lostFolderPath = "lost-images"
output_file = "sv_embeddings.json"
embeddings = []
backends = [
'opencv',
'ssd',
'dlib',
'mtcnn',
'fastmtcnn',
'retinaface',
'mediapipe',
'yolov8',
'yunet',
'centerface',
]
def main():
video_folders = setup()
for folder_info in video_folders:
foldername, video_path, image_paths = folder_info
print(f"Processing {foldername}\n")
run(image_paths, foldername, video_path)
saveToJson()
def processImage(image, idx, foldername, video_path):
try:
print(f"Processing {image}", end="\r")
# Initialize variables to accumulate sums
sums = {
'angry': 0,
'disgust': 0,
'fear': 0,
'happy': 0,
'sad': 0,
'surprise': 0,
'neutral': 0
}
anaylse_obj = DeepFace.analyze(
img_path=image,
actions=['emotion'],
enforce_detection=True,
detector_backend=backends[5],
silent=True
)
emotions = anaylse_obj[0]['emotion']
selected_emotions = [
emotions['happy'],
emotions['sad'],
emotions['angry'],
emotions['neutral']
]
num_of_faces = len(anaylse_obj)
# Get average emotion
# for face in anaylse_obj:
# emotions = face['emotion']
# for emotion in sums:
# sums[emotion] += emotions.get(emotion, 0)
# averages = {emotion: sums[emotion] / num_of_faces for emotion in sums}
raw_emotions = [value for value in emotions.values()]
#normalized_emotions = [value / 100 for value in raw_emotions]
normalized_emotions = [value / 100 for value in selected_emotions]
#normalised_emotions = l2_normalize(np.array(raw_emotions))
# normalised_emotions = normalised_emotions.tolist()
entry = {
"folder": foldername,
"image": image, # Extract the filename from the path
"error": 0,
"vector": normalized_emotions
}
# Add the entry to the JSON data list
embeddings.append(entry)
except:
# if model does not detect any emotions
# set lost -> 1 & generate a random emotion vector
random_vector = np.random.rand(4)
random_vector_list = random_vector.tolist()
entry = {
"folder": foldername,
"image": image, # Extract the filename from the path
"error": 1,
"vector": random_vector_list
}
# Add the entry to the JSON data list
embeddings.append(entry)
pass
print(entry["vector"])
def setup():
video_folders = []
subfolders = [f.path for f in os.scandir(baseFolderPath) if f.is_dir()]
for subfolder in subfolders:
frames_folder_path = os.path.join(subfolder, "segmented_images")
# Find the video file in the subfolder
# video_files = [f for f in os.listdir(subfolder) if f.endswith(('.mp4', '.avi', '.mov'))]
# if video_files:
# video_path = os.path.join(subfolder, video_files[0])
# List of all image files in the frames folder
image_files = glob.glob(os.path.join(frames_folder_path, '*'))
# Filter by specific image extensions (e.g., .jpg, .png)
image_paths = [img for img in image_files if img.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.gif'))]
# Sort the image paths by filename (assuming the filenames are numerically ordered)
image_paths.sort(key=lambda x: int(os.path.splitext(os.path.basename(x))[0]))
video_path = "null"
# Add the information to the list
video_folders.append((os.path.basename(subfolder), video_path, image_paths))
return video_folders
def run(image_paths, foldername, video_path):
for idx, image in enumerate(image_paths):
processImage(image, idx, foldername, video_path)
def l2_normalize(vector):
norm = np.linalg.norm(vector)
if norm == 0:
return vector
return vector / norm
def saveToJson():
with open(output_file, 'w') as f:
json.dump(embeddings, f, indent=4)
print("Successfully created JSON file.")
if __name__ == "__main__":
main()

117
process_video.py

@ -0,0 +1,117 @@
import os
import subprocess
import re
import shutil
def convert_video(video_path, output_path):
print(f"Converting video, {video_path}")
# Codec that works with openframeworks!
command = [
"ffmpeg",
"-i", video_path, # Input file
"-c:v", "libx264", # Video codec
"-profile:v", "high", # Video profile
"-c:a", "copy", # Copy audio without re-encoding
output_path # Output file
]
results = subprocess.run(command, stderr=subprocess.PIPE, text=True)
output = results.stderr
print(f"Video converted {output}")
def get_frame_rate(video_path):
"""
Get the frame rate of a video file using ffmpeg.
"""
command = [
'ffmpeg',
'-i', video_path,
'-vcodec', 'png',
'-f', 'null',
'-'
]
result = subprocess.run(command, stderr=subprocess.PIPE, text=True)
output = result.stderr
match = re.search(r'(\d+(\.\d+)?) fps', output)
if match:
return float(match.group(1))
else:
raise ValueError("Frame rate not found in video information.")
def extract_frames_from_video(video_path, output_folder):
"""
Extract frames from a video file at 1 fps.
"""
os.makedirs(output_folder, exist_ok=True)
command = [
'ffmpeg',
'-i', video_path, # Input file
'-vf', 'fps=1/10', # Extract 1 frame per second
'-vsync', 'vfr', # Variable frame rate
os.path.join(output_folder, 'frame_%09d.png') # Output pattern
]
subprocess.run(command, check=True)
def rename_frames(output_folder, frame_rate):
"""
Rename the extracted frames to match their original frame numbers.
"""
frame_files = sorted(f for f in os.listdir(output_folder) if f.startswith('frame_') and f.endswith('.png'))
for i, filename in enumerate(frame_files):
# Calculate the original frame number
original_frame_number = int(i * frame_rate)
# Create the new filename with the original frame number
new_filename = f"{original_frame_number:09d}.png"
os.rename(
os.path.join(output_folder, filename),
os.path.join(output_folder, new_filename)
)
def process_videos_in_folder(folder_path):
"""
Process all video files in the specified folder and extract frames from each video.
"""
for filename in os.listdir(folder_path):
if filename.lower().endswith(('.mp4', '.avi', '.mov', '.mkv', '.flv')):
video_path = os.path.join(folder_path, filename)
output_folder = os.path.join(folder_path, os.path.splitext(filename)[0]) # Create a folder for each video
# New location for .mp4
video_copy_location = os.path.join(output_folder, filename)
# Create frames folder
frames_folder = os.path.join(output_folder, "frames")
if not os.path.exists(output_folder):
os.mkdir(output_folder)
if not os.path.exists(frames_folder):
os.mkdir(frames_folder)
print(f'Processing video: {video_path}')
try:
#convert_video(video_path, video_copy_location)
frame_rate = get_frame_rate(video_path)
print(f'Original frame rate: {frame_rate} fps')
extract_frames_from_video(video_path, frames_folder)
rename_frames(frames_folder, frame_rate)
print(f'Frames saved and renamed to: {frames_folder}')
except ValueError as e:
print(f'Error processing video {video_path}: {e}')
if __name__ == "__main__":
# Path to the folder containing videos
folder_path = 'main_dataset'
process_videos_in_folder(folder_path)

74
requirements.txt

@ -0,0 +1,74 @@
absl-py==2.1.0
astunparse==1.6.3
beautifulsoup4==4.12.3
blinker==1.8.2
certifi==2024.7.4
charset-normalizer==3.3.2
click==8.1.7
deepface==0.0.93
filelock==3.15.4
fire==0.6.0
Flask==3.0.3
Flask-Cors==5.0.0
flatbuffers==24.3.25
gast==0.6.0
gdown==5.2.0
google-pasta==0.2.0
grpcio==1.65.4
gunicorn==23.0.0
h5py==3.11.0
idna==3.7
importlib_metadata==8.2.0
itsdangerous==2.2.0
Jinja2==3.1.4
keras==3.5.0
libclang==18.1.1
Markdown==3.6
markdown-it-py==3.0.0
MarkupSafe==2.1.5
mdurl==0.1.2
ml-dtypes==0.4.0
mtcnn==0.1.1
namex==0.0.8
numpy==1.26.4
nvidia-cublas-cu12==12.3.4.1
nvidia-cuda-cupti-cu12==12.3.101
nvidia-cuda-nvcc-cu12==12.3.107
nvidia-cuda-nvrtc-cu12==12.3.107
nvidia-cuda-runtime-cu12==12.3.101
nvidia-cudnn-cu12==8.9.7.29
nvidia-cufft-cu12==11.0.12.1
nvidia-curand-cu12==10.3.4.107
nvidia-cusolver-cu12==11.5.4.101
nvidia-cusparse-cu12==12.2.0.103
nvidia-nccl-cu12==2.19.3
nvidia-nvjitlink-cu12==12.3.101
opencv-python==4.10.0.84
opt-einsum==3.3.0
optree==0.12.1
packaging==24.1
pandas==2.2.2
pillow==10.4.0
protobuf==4.25.4
Pygments==2.18.0
PySocks==1.7.1
python-dateutil==2.9.0.post0
pytz==2024.1
requests==2.32.3
retina-face==0.0.17
rich==13.7.1
six==1.16.0
soupsieve==2.6
tensorboard==2.17.1
tensorboard-data-server==0.7.2
tensorflow==2.17.0
tensorflow-io-gcs-filesystem==0.37.1
termcolor==2.4.0
tf_keras==2.17.0
tqdm==4.66.5
typing_extensions==4.12.2
tzdata==2024.1
urllib3==2.2.2
Werkzeug==3.0.3
wrapt==1.16.0
zipp==3.20.0

90675
sv_embeddings.json

File diff suppressed because it is too large
Loading…
Cancel
Save