Commit 9e9f8e78 authored by Ivan Chekanov's avatar Ivan Chekanov
Browse files

:sparkles: Add solution

parent 5e7d7257
No related merge requests found
Showing with 790 additions and 0 deletions
+790 -0
*.onnx
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,python,macos,windows,jupyternotebooks
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,python,macos,windows,jupyternotebooks
......
import os
import requests
import cv2
DIRECTORY = "lab-4"
# Инициализация детектора лиц YuNET
if not os.path.exists(f"{DIRECTORY}/face_detection_yunet_2023mar.onnx"):
print("Загрузка face_detection_yunet_2023mar.onnx ...")
url = "https://github.com/opencv/opencv_zoo/raw/refs/heads/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx"
response = requests.get(url)
with open(f"{DIRECTORY}/face_detection_yunet_2023mar.onnx", "wb") as f:
f.write(response.content)
print("Загрузка face_detection_yunet_2023mar.onnx завершена")
detector = cv2.FaceDetectorYN.create(
f"{DIRECTORY}/face_detection_yunet_2023mar.onnx", "", (320, 320), 0.9, 0.3, 5000
)
# Инициализация распознавателя лиц
if not os.path.exists(f"{DIRECTORY}/face_recognition_sface_2021dec.onnx"):
print("Загрузка face_recognition_sface_2021dec.onnx ...")
url = "https://github.com/opencv/opencv_zoo/raw/refs/heads/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx"
response = requests.get(url)
with open(f"{DIRECTORY}/face_recognition_sface_2021dec.onnx", "wb") as f:
f.write(response.content)
print("Загрузка face_recognition_sface_2021dec.onnx завершена")
recognizer = cv2.FaceRecognizerSF.create(
f"{DIRECTORY}/face_recognition_sface_2021dec.onnx", ""
)
# Загрузка референсного изображения
ref_image = cv2.imread(f"{DIRECTORY}/task_1_reference.jpg")
if ref_image is None:
print("Не удалось загрузить референсное изображение")
exit()
# Обнаружение лица на референсном изображении
height, width = ref_image.shape[:2]
detector.setInputSize((width, height))
_, faces = detector.detect(ref_image)
if faces is None:
print("На референсном изображении не найдено лиц")
exit()
# Извлечение признаков референсного лица
ref_face = faces[0]
aligned_ref_face = recognizer.alignCrop(ref_image, ref_face)
ref_feature = recognizer.feature(aligned_ref_face)
# Инициализация видеопотока с веб-камеры
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Не удалось открыть веб-камеру")
exit()
# Порог косинусного сходства для распознавания
COSINE_THRESHOLD = 0.4
L2_THRESHOLD = 1.2
while True:
ret, frame = cap.read()
if not ret:
print("Не удалось получить кадр")
break
# Обнаружение лиц в кадре
frame_height, frame_width = frame.shape[:2]
detector.setInputSize((frame_width, frame_height))
_, faces = detector.detect(frame)
if faces is not None:
for face in faces:
# Получение координат ограничивающего прямоугольника
bbox = list(map(int, face[:4]))
x, y, w, h = bbox
# Извлечение признаков текущего лица
aligned_face = recognizer.alignCrop(frame, face)
current_feature = recognizer.feature(aligned_face)
# Сравнение с референсным лицом
cosine_score = recognizer.match(
ref_feature, current_feature, cv2.FaceRecognizerSF_FR_COSINE
)
l2_score = recognizer.match(
ref_feature, current_feature, cv2.FaceRecognizerSF_FR_NORM_L2
)
# Определение цвета прямоугольника
color = (0, 0, 255) # Красный по умолчанию
if cosine_score >= COSINE_THRESHOLD or l2_score <= L2_THRESHOLD:
print(f"{cosine_score=:.3f}, {l2_score=:.3f}")
if cosine_score >= COSINE_THRESHOLD and l2_score <= L2_THRESHOLD:
print("Сработали оба порога")
elif cosine_score >= COSINE_THRESHOLD:
print("Сработал порог косинусного сходства")
elif l2_score <= L2_THRESHOLD:
print("Сработал порог L2 сходства")
color = (0, 255, 0) # Зеленый для референсного лица
# Отрисовка прямоугольника
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
# Отображение результата
cv2.imshow("Face Detection", frame)
# Выход по нажатию 'q'
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# Освобождение ресурсов
cap.release()
cv2.destroyAllWindows()
lab-4/task_1_reference.jpg

222 KB

# app.py
import os
import numpy as np
import streamlit as st
from deepface import DeepFace
from PIL import Image
import faiss
import pandas as pd
# Конфигурации
EMBEDDING_SIZE = 128 # Для FaceNet
DATABASE_PATH = "lab-4/task_2_faces"
INDEX_PATH = "lab-4/task_2_faiss_index.index"
NAMES_PATH = "lab-4/task_2_names.npy"
STAFF_CSV = "lab-4/task_2_staff_photo.csv" # Добавим путь к CSV файлу
def build_faiss_database():
st.write("Построение базы данных...")
if not os.path.exists(DATABASE_PATH):
st.error("Папка с лицами не найдена, создаю папку")
st.write("Загрузите изображения лиц в папку и нажмите кнопку 'Построить/Обновить базу' ещё раз")
os.makedirs(DATABASE_PATH)
return
# Загрузка данных о сотрудниках
try:
staff_df = pd.read_csv(STAFF_CSV)
filename_to_name = dict(zip(staff_df['filename'], staff_df['name']))
except Exception as e:
st.error(f"Ошибка чтения CSV файла: {str(e)}")
return
embeddings = []
names = []
progress_bar = st.progress(0)
files = sorted(os.listdir(DATABASE_PATH))
mx = len(files)
for i, img_file in enumerate(files):
img_path = os.path.join(DATABASE_PATH, img_file)
try:
# Извлечение лица и эмбеддинга
img = Image.open(img_path)
face = DeepFace.extract_faces(img_path=img_path, detector_backend='opencv')[0]
embedding = DeepFace.represent(
img_path=img_path,
model_name='Facenet',
detector_backend='opencv'
)[0]['embedding']
embeddings.append(embedding)
# Используем имя из CSV вместо имени файла
person_name = filename_to_name.get(img_file, img_file)
names.append(person_name)
except Exception as e:
st.error(f"Ошибка обработки {img_path}: {str(e)}")
progress_bar.progress(i / mx)
if len(embeddings) == 0:
return
# Создание FAISS индекса
embeddings = np.array(embeddings).astype('float32')
index = faiss.IndexFlatL2(EMBEDDING_SIZE)
index.add(embeddings)
# Сохранение индекса и имен
faiss.write_index(index, INDEX_PATH)
np.save(NAMES_PATH, np.array(names))
st.success(f"База данных построена: {len(names)} лиц")
def search_face(query_img, threshold=0.5):
if not os.path.exists(INDEX_PATH):
st.error("Сначала постройте базу данных")
return None, None
try:
# Конвертация PIL Image в numpy array
query_img_array = np.array(query_img)
# Извлечение эмбеддинга для запроса
face = DeepFace.extract_faces(img_path=query_img_array, detector_backend='opencv')[0]
query_embedding = DeepFace.represent(
img_path=query_img_array,
model_name='Facenet',
detector_backend='opencv'
)[0]['embedding']
# Поиск в FAISS
index = faiss.read_index(INDEX_PATH)
names = np.load(NAMES_PATH)
# Поиск ближайшего соседа
query_embedding = np.array([query_embedding]).astype('float32')
distances, indices = index.search(query_embedding, 1)
if distances[0][0] <= threshold:
return names[indices[0][0]], distances[0][0]
else:
return "Unknown", distances[0][0]
except Exception as e:
st.error(f"Ошибка распознавания: {str(e)}")
return None, None
# Streamlit интерфейс
st.title("🔍 Face Recognition System")
# Секция для построения базы данных
st.sidebar.header("База данных лиц")
if st.sidebar.button("Построить/Обновить базу"):
build_faiss_database()
# Секция для поиска
st.header("Поиск лица")
uploaded_file = st.file_uploader("Загрузите изображение лица", type=['jpg', 'png', 'jpeg'])
if uploaded_file is not None:
image = Image.open(uploaded_file)
st.image(image, caption="Загруженное изображение", use_container_width=True)
if st.button("Найти совпадения"):
name, distance = search_face(image, threshold=1000)
if name:
st.subheader(f"Результат: {name}")
st.write(f"Расстояние: {distance:.4f}")
if name == "Unknown":
st.error("Совпадений не найдено в базе данных")
else:
st.success("Совпадение найдено!")
# Загружаем данные о сотрудниках
staff_df = pd.read_csv(STAFF_CSV)
# Ищем запись сотрудника по имени
staff_record = staff_df[staff_df['name'] == name]
if not staff_record.empty:
# Получаем имя файла фотографии
photo_filename = staff_record.iloc[0]['filename']
photo_path = os.path.join(DATABASE_PATH, photo_filename)
if os.path.exists(photo_path):
matched_image = Image.open(photo_path)
st.image(matched_image, caption=f"Фотография сотрудника: {name}",
use_container_width=True)
\ No newline at end of file
import cv2
import pandas as pd
import numpy as np
from deepface import DeepFace
from tqdm import tqdm
import os
import pickle
import hashlib
# Конфигурация
VIDEO_DIR = "lab-4/task_3_1_references/videos"
TIMECODE_CSV_DIR = "lab-4/task_3_1_references/labels"
REFERENCE_DIR = "lab-4/task_3_1_references/photos"
CACHE_FILE = "lab-4/task_3_1_cache/embeddings_cache.pkl"
DIR_HASH_FILE = "lab-4/task_3_1_cache/dir_hash.txt"
THRESHOLD = 0.1 # Порог косинусного сходства
FRAME_SKIP = 50 # Каждый 50-й кадр
video_files = [f for f in os.listdir(VIDEO_DIR) if f.endswith((".mp4", ".avi", ".mov"))]
print("Доступные видео:")
for idx, video in enumerate(video_files):
print(f"{idx + 1}: {video}")
video_choice = int(input("Выберите номер видео для обработки: ")) - 1
VIDEO_PATH = os.path.join(VIDEO_DIR, video_files[video_choice])
# Загрузка соответствующего файла с таймкодами
TIMECODE_CSV = os.path.join(
TIMECODE_CSV_DIR,
video_files[video_choice].replace(video_files[video_choice].split(".")[-1], "csv"),
)
def get_dir_hash(directory):
"""Вычисляет хэш директории на основе имен файлов и их размеров"""
hash_md5 = hashlib.md5()
for root, _, files in os.walk(directory):
for file in sorted(files): # сортировка для стабильности хэша
filepath = os.path.join(root, file)
file_size = os.path.getsize(filepath)
hash_md5.update(f"{filepath}{file_size}".encode())
return hash_md5.hexdigest()
def normalize_embedding(embedding):
return embedding / np.linalg.norm(embedding)
def load_reference_embeddings():
# Проверяем существующий кэш
current_hash = get_dir_hash(REFERENCE_DIR)
if os.path.exists(CACHE_FILE) and os.path.exists(DIR_HASH_FILE):
with open(DIR_HASH_FILE, "r") as f:
cached_hash = f.read().strip()
if cached_hash == current_hash:
print("Загрузка эмбеддингов из кэша...")
with open(CACHE_FILE, "rb") as f:
return pickle.load(f)
print("Вычисление новых эмбеддингов...")
embeddings = {}
for person in tqdm(os.listdir(REFERENCE_DIR)):
person_dir = os.path.join(REFERENCE_DIR, person)
if os.path.isdir(person_dir):
for img_name in os.listdir(person_dir):
img_path = os.path.join(person_dir, img_name)
try:
# Сначала извлекаем лицо
faces = DeepFace.extract_faces(
img_path=img_path,
detector_backend="opencv",
enforce_detection=False,
)
if faces: # Если лицо найдено
# Получаем эмбеддинг для найденного лица
embedding = normalize_embedding(
DeepFace.represent(
img_path=faces[0][
"face"
], # Используем извлеченное лицо
model_name="Facenet",
detector_backend="opencv",
enforce_detection=False,
)[0]["embedding"]
)
if person not in embeddings:
embeddings[person] = []
embeddings[person].append(embedding)
except Exception as e:
print(f"Ошибка обработки {img_path}: {str(e)}")
continue
# Сохраняем новый кэш
with open(CACHE_FILE, "wb") as f:
pickle.dump(embeddings, f)
with open(DIR_HASH_FILE, "w") as f:
f.write(current_hash)
return embeddings
print("\nЗагрузка эталонных эмбеддингов...")
reference_embeddings = load_reference_embeddings()
print(f"Загружено {len(reference_embeddings)} эталонных личностей")
# Загрузка разметки
print("\nЗагрузка разметки из CSV...")
timecodes = pd.read_csv(TIMECODE_CSV)
timecodes["from"] = pd.to_timedelta(timecodes["from"]).dt.total_seconds()
timecodes["to"] = pd.to_timedelta(timecodes["to"]).dt.total_seconds()
# Преобразование строки persons в список
timecodes["persons"] = timecodes["persons"].apply(
lambda x: [person.strip() for person in x.split(",")] if isinstance(x, str) else x
)
print(f"Загружено {len(timecodes)} временных меток")
# Инициализация видео
print("\nИнициализация видео...")
cap = cv2.VideoCapture(VIDEO_PATH)
fps = cap.get(cv2.CAP_PROP_FPS)
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"FPS: {fps:.2f}")
print(f"Всего кадров: {total_frames}")
print(f"Длительность видео: {total_frames/fps:.2f} секунд")
# Метрики
true_positives = 0
false_positives = 0
print("\nНачинаем обработку кадров...")
# Обработка кадров
for frame_num in tqdm(range(0, total_frames, FRAME_SKIP)):
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
ret, frame = cap.read()
if not ret:
break
# Определение текущего времени
current_time = frame_num / fps
# Получение ожидаемых лиц
current_frames = timecodes[
(timecodes["from"] <= current_time) & (timecodes["to"] >= current_time)
]
expected = []
for persons_list in current_frames["persons"]:
if isinstance(persons_list, list):
expected.extend(persons_list)
expected = list(set(expected)) # удаление дубликатов
try:
# Обнаружение лиц
detected_faces = DeepFace.extract_faces(
frame, detector_backend="opencv", enforce_detection=False
)
except Exception as exc:
print(f"Поиск на кадре {frame_num} не удался: {exc=}")
continue
# print(f"{expected=}")
for face in detected_faces:
try:
# Получение эмбеддинга
query_embedding = normalize_embedding(
DeepFace.represent(
img_path=face["face"],
model_name="Facenet",
detector_backend="opencv",
enforce_detection=False,
)[0]["embedding"]
)
# Поиск совпадений
best_match = ("Unknown", 1)
for person, embeddings in reference_embeddings.items():
avg_distance = np.mean(
[np.linalg.norm(query_embedding - emb) for emb in embeddings]
)
if avg_distance < best_match[1]:
best_match = (person, avg_distance)
# Проверка совпадения
# print(f"{best_match=}")
if best_match[1] > THRESHOLD:
if best_match[0] in expected:
true_positives += 1
else:
false_positives += 1
else:
false_positives += 1
except Exception as exc:
print(f"Сопоставление на кадре {frame_num} не удалось: {exc=}")
false_positives += 1
# Расчет точности
precision = (
true_positives / (true_positives + false_positives)
if (true_positives + false_positives) > 0
else 0
)
print("\nРезультаты анализа:")
print(f"Правильные обнаружения (True Positives): {true_positives}")
print(f"Ложные обнаружения (False Positives): {false_positives}")
print(f"Precision: {precision:.4f}")
cap.release()
print("\nОбработка завершена!")
"""## Часть 2. Оценить точность работы методов из DeepFace на аугментированных данных (2 балла).
Необходимо собрать собственный набор данных из **различных** изображений Вашего лица с разных ракурсов, желательно настоящие фотографии из личного архива (20 штук)\
Возьмите эталонное изображение (как в паспорте) и при помощи библиотеки [DeepFace](https://github.com/serengil/deepface) проверьте его на соответствие всему датасету. Посчитайте метрику Precision. \
\
Примените каждую из перечисленных ниже аугментаций (**по-отдельности**) ко всему датасету и измерьте метрику Precision для измененнного датасета:
* Поворот изображения на 45° и 90°.
* Добавление шума (Gaussian Noise).
* Изменение яркости (увеличение и уменьшение на 50%).
* Размытие с различными параметрами.
\
Реузультаты соберите в таблицу вида:
Метод | Исходный датасет | Поворот на 45° | Поворот на 90° | Изображение с шумом |
--- | ----|--- | --- | --- |
VGG-Face | 0 | 0 | 0 | 0 |
Facenet | 0 | 0 | 0 | 0 |
Facenet512 | 0 | 0 | 0 | 0 |
OpenFace | 0 | 0 | 0 | 0 |
DeepFace | 0 | 0 | 0 | 0 |
DeepID | 0 | 0 | 0 | 0 |
ArcFace | 0 | 0 | 0 | 0 |
Dlib | 0 | 0 | 0 | 0 |
SFace | 0 | 0 | 0 | 0 |
GhostFaceNet | 0 | 0 | 0 | 0 |
"""
import os
import cv2
import numpy as np
from deepface import DeepFace
from PIL import Image, ImageEnhance, ImageFilter
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
# Путь к эталонному изображению
reference_image_path = "lab-4/task_3_2_reference.jpg"
# Путь к папке с изображениями датасета
dataset_folder = "lab-4/task_3_2_references"
image_paths = [os.path.join(dataset_folder, img) for img in os.listdir(dataset_folder)]
"""Поворот на 45 и 90 градусов:"""
def rotate_image(image, angle):
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h))
return rotated
"""Добавление шума:"""
def add_noise(image):
row, col, ch = image.shape
mean = 0
var = 0.1
sigma = var**0.5
gauss = np.random.normal(mean, sigma, (row, col, ch))
gauss = gauss.reshape(row, col, ch)
noisy = image + gauss * 50
return noisy.astype(np.uint8)
"""Изменение яркости:"""
def adjust_brightness(image, factor):
img = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
enhancer = ImageEnhance.Brightness(img)
brightened = enhancer.enhance(factor)
return cv2.cvtColor(np.array(brightened), cv2.COLOR_RGB2BGR)
"""Размытие:"""
def apply_blur(image, kernel_size=(5, 5)):
return cv2.GaussianBlur(image, kernel_size, 0)
def apply_average_blur(image, kernel_size=(5, 5)):
return cv2.blur(image, kernel_size)
def apply_bilateral_blur(image, d=9, sigma_color=75, sigma_space=75):
return cv2.bilateralFilter(image, d, sigma_color, sigma_space)
"""Распознавание лиц:"""
def calculate_recall(reference_embedding, dataset_embeddings, threshold=0.5):
print(f"Вычисление метрики recall с порогом {threshold}")
true_positives = 0
false_negatives = 0
for i, embedding_list in enumerate(dataset_embeddings):
if isinstance(embedding_list, list) and len(embedding_list) > 0:
embedding_dict = embedding_list[0]
if isinstance(embedding_dict, dict) and "embedding" in embedding_dict:
embedding = np.array(embedding_dict["embedding"])
distance = np.linalg.norm(reference_embedding - embedding)
if distance < threshold:
true_positives += 1
else:
false_negatives += 1
else:
print(
f"Предупреждение: Неожиданный формат embedding_dict в элементе {i+1}"
)
false_negatives += 1
else:
print(f"Предупреждение: Лицо не обнаружено в элементе {i+1}")
false_negatives += 1
recall = true_positives / 20
print(
f"Вычисление recall завершено, {recall=:.3f}. Истинно положительных: {true_positives}, Ложно отрицательных: {false_negatives}"
)
return recall
def test_transformations(image_paths):
results = {
model: {}
for model in [
"Facenet",
"VGG-Face",
"Facenet512",
"OpenFace",
# "DeepFace",
"DeepID",
"ArcFace",
"Dlib",
"SFace",
"GhostFaceNet",
]
}
for model_name in results.keys():
print(f"\nТестирование модели: {model_name}")
# First extract face from reference image
print("Извлечение лица из эталонного изображения...")
try:
faces = DeepFace.extract_faces(
img_path=reference_image_path,
detector_backend="opencv",
enforce_detection=False,
)
if faces:
# Get reference embedding using extracted face
print("Получение эталонного эмбеддинга...")
reference_embedding_list = DeepFace.represent(
img_path=faces[0]["face"],
model_name=model_name,
detector_backend="opencv",
enforce_detection=False,
)
reference_embedding = np.array(reference_embedding_list[0]["embedding"])
else:
print("Лицо не обнаружено в эталонном изображении")
continue
except Exception as e:
print(f"Ошибка при обработке эталонного изображения: {str(e)}")
continue
print("Обработка исходного датасета...")
original_embeddings = process_dataset(image_paths, model_name=model_name)
results[model_name]["Исходный датасет"] = calculate_recall(
reference_embedding, original_embeddings
)
print("Обработка поворота на 45°...")
rotated_45_embeddings = process_dataset(
image_paths,
model_name=model_name,
transform=lambda img: rotate_image(img, 45),
transform_name="Поворот на 45°",
)
results[model_name]["Поворот на 45°"] = calculate_recall(
reference_embedding, rotated_45_embeddings
)
print("Обработка поворота на 90°...")
rotated_90_embeddings = process_dataset(
image_paths,
model_name=model_name,
transform=lambda img: rotate_image(img, 90),
transform_name="Поворот на 90°",
)
results[model_name]["Поворот на 90°"] = calculate_recall(
reference_embedding, rotated_90_embeddings
)
print("Обработка изображений с шумом...")
noisy_embeddings = []
res = process_dataset(
image_paths,
model_name=model_name,
transform=add_noise,
transform_name="Изображение с шумом",
)
noisy_embeddings.extend(res)
res = process_dataset(
image_paths,
model_name=model_name,
transform=lambda img: adjust_brightness(img, 0.5),
transform_name="Изображение с уменьшенной яркостью",
)
noisy_embeddings.extend(res)
res = process_dataset(
image_paths,
model_name=model_name,
transform=lambda img: adjust_brightness(img, 1.5),
transform_name="Изображение с увеличенной яркостью",
)
noisy_embeddings.extend(res)
res = process_dataset(
image_paths,
model_name=model_name,
transform=apply_blur,
transform_name="Размытие",
)
noisy_embeddings.extend(res)
results[model_name]["Изображение с шумом"] = calculate_recall(
reference_embedding, noisy_embeddings
)
return results
def process_dataset(image_paths, model_name, transform=None, transform_name="Без трансформации"):
embeddings = []
for img_path in tqdm(
image_paths,
desc=f"Обработка изображений ({model_name}, трансформация={transform_name})",
):
try:
img = cv2.imread(img_path)
if transform:
img = transform(img)
# First extract face
faces = DeepFace.extract_faces(
img_path=img, detector_backend="opencv", enforce_detection=False
)
if faces: # If face was found
# Get embedding using the extracted face
embedding_list = DeepFace.represent(
img_path=faces[0]["face"], # Use the extracted face
model_name=model_name,
detector_backend="opencv",
enforce_detection=False,
)
embeddings.append(embedding_list)
else:
print(f"Лицо не обнаружено в {os.path.basename(img_path)}")
embeddings.append([])
except Exception as e:
print(
f"Ошибка обработки {os.path.basename(img_path)} моделью {model_name}: {str(e)}"
)
embeddings.append([])
return embeddings
def create_results_table(results):
# Convert results dictionary to DataFrame format
data = {
"Метод": list(results.keys()),
"Исходный датасет": [results[model]["Исходный датасет"] for model in results],
"Поворот на 45°": [results[model]["Поворот на 45°"] for model in results],
"Поворот на 90°": [results[model]["Поворот на 90°"] for model in results],
"Изображение с шумом": [
results[model]["Изображение с шумом"] for model in results
],
}
results_df = pd.DataFrame(data)
return results_df
def main():
print("Запуск оценки распознавания лиц...")
print(f"Используется эталонное изображение: {reference_image_path}")
print(f"Папка с датасетом: {dataset_folder}")
results = test_transformations(image_paths)
print("\nСоздание таблицы результатов...")
results_df = create_results_table(results)
print("\nТаблица результатов:")
print(results_df)
print("\nСохранение результатов в CSV...")
results_df.to_csv("lab-4/task_3_2_results.csv", index=False)
print("Результаты успешно сохранены")
if __name__ == "__main__":
main()
lab-4/task_3_2_reference.jpg

1.39 MB

Метод,Исходный датасет,Поворот на 45°,Поворот на 90°,Изображение с шумом
Facenet,1.0,1.0,1.0,4.0
VGG-Face,0.0,0.0,0.0,0.0
Facenet512,1.0,1.0,1.0,4.0
OpenFace,1.0,1.0,1.0,4.0
DeepID,0.95,0.95,0.95,3.8
ArcFace,1.0,1.0,1.0,4.0
Dlib,1.0,1.0,1.0,4.0
SFace,1.0,1.0,1.0,3.4
GhostFaceNet,0.95,0.65,0.5,3.65
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment