From 1a0249c4ebd370138141a0bc96bc9cbce3d4d5d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9F=D0=B0=D1=80=D1=88=D0=B8=D0=BD=D0=B0=20=D0=95=D0=BA?=
 =?UTF-8?q?=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=BD=D0=B0=20=D0=A1=D0=B5=D1=80?=
 =?UTF-8?q?=D0=B3=D0=B5=D0=B5=D0=B2=D0=BD=D0=B0?= <esparshina@miem.hse.ru>
Date: Sat, 1 Feb 2025 20:16:03 +0000
Subject: [PATCH] Upload New File

---
 HW 4/Task3/task_3.ipynb | 398 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 398 insertions(+)
 create mode 100644 HW 4/Task3/task_3.ipynb

diff --git a/HW 4/Task3/task_3.ipynb b/HW 4/Task3/task_3.ipynb
new file mode 100644
index 0000000..209b961
--- /dev/null
+++ b/HW 4/Task3/task_3.ipynb	
@@ -0,0 +1,398 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "7b42cfcb-38f0-425b-abc0-e7c27fe9e3af",
+   "metadata": {},
+   "source": [
+    "#Задание 3. Часть 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f53c99ca-93cd-4324-a643-69c0cbbb670d",
+   "metadata": {},
+   "source": [
+    "Необходимо собрать собственный набор данных из **различных** изображений Вашего лица с разных ракурсов, желательно настоящие фотографии из личного архива (20 штук)\\\n",
+    "Возьмите эталонное изображение (как в паспорте) и при помощи библиотеки [DeepFace](https://github.com/serengil/deepface) проверьте его на соответствие всему датасету. Посчитайте метрику Precision. \\\n",
+    "\\\n",
+    "Примените каждую из перечисленных ниже аугментаций (**по-отдельности**) ко всему датасету и измерьте метрику Precision для измененнного датасета:\n",
+    "*   Поворот изображения на 45° и 90°.\n",
+    "*   Добавление шума (Gaussian Noise).\n",
+    "*   Изменение яркости (увеличение и уменьшение на 50%).\n",
+    "*   Размытие с различными параметрами.\n",
+    "\\\n",
+    "Реузультаты соберите в таблицу вида:\n",
+    "\n",
+    "Метод | Исходный датасет | Поворот на 45° | Поворот на 90° | Изображение с шумом |\n",
+    "--- | ----|--- | --- | --- |\n",
+    "VGG-Face | 0 | 0 | 0 | 0 |\n",
+    "Facenet | 0 | 0 | 0 | 0 |\n",
+    "Facenet512 | 0 | 0 | 0 | 0 |\n",
+    "OpenFace | 0 | 0 | 0 | 0 |\n",
+    "DeepFace | 0 | 0 | 0 | 0 |\n",
+    "DeepID | 0 | 0 | 0 | 0 |\n",
+    "ArcFace | 0 | 0 | 0 | 0 |\n",
+    "Dlib | 0 | 0 | 0 | 0 |\n",
+    "SFace | 0 | 0 | 0 | 0 |\n",
+    "GhostFaceNet | 0 | 0 | 0 | 0 |"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "6d82b3d9-2e3c-4726-9bdb-72d340c29e5a",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2025-02-01 14:08:36.104207: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
+      "2025-02-01 14:08:36.113857: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
+      "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
+      "E0000 00:00:1738408116.124793  227811 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
+      "E0000 00:00:1738408116.128118  227811 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
+      "2025-02-01 14:08:36.139691: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
+      "To enable the following instructions: AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
+      "W0000 00:00:1738408118.299641  227811 gpu_device.cc:2344] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n",
+      "Skipping registering GPU devices...\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "          Метод  Исходный набор  Поворот на 45°  Поворот на 90°  \\\n",
+      "0      VGG-Face            0.60            0.05            0.00   \n",
+      "1    Facenet512            0.20            0.00            0.00   \n",
+      "2      OpenFace            0.00            0.00            0.00   \n",
+      "3        DeepID            0.15            0.05            0.05   \n",
+      "4       ArcFace            0.55            0.05            0.00   \n",
+      "5          Dlib            0.60            0.05            0.00   \n",
+      "6         SFace            0.45            0.05            0.00   \n",
+      "7  GhostFaceNet            0.50            0.05            0.00   \n",
+      "\n",
+      "   Изображение с шумом  Увеличенная яркость  Уменьшенная яркость  Размытие  \n",
+      "0                 0.05                 0.55                 0.65      0.60  \n",
+      "1                 0.00                 0.35                 0.15      0.25  \n",
+      "2                 0.00                 0.00                 0.00      0.05  \n",
+      "3                 0.00                 0.15                 0.15      0.15  \n",
+      "4                 0.00                 0.55                 0.65      0.60  \n",
+      "5                 0.10                 0.50                 0.70      0.65  \n",
+      "6                 0.00                 0.45                 0.60      0.50  \n",
+      "7                 0.05                 0.40                 0.55      0.55  \n"
+     ]
+    }
+   ],
+   "source": [
+    "import os\n",
+    "import cv2\n",
+    "import numpy as np\n",
+    "import pandas as pd\n",
+    "from deepface import DeepFace\n",
+    "from sklearn.metrics import recall_score\n",
+    "\n",
+    "image_dir = \"kate\"\n",
+    "reference_image_path = \"user.jpg\"\n",
+    "\n",
+    "models = ['VGG-Face', 'Facenet512', 'OpenFace', 'DeepID', 'ArcFace', 'Dlib', 'SFace', 'GhostFaceNet']\n",
+    "\n",
+    "def rotate_image(image, angle):\n",
+    "    center = tuple(np.array(image.shape[1::-1]) / 2)\n",
+    "    rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0)\n",
+    "    return cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)\n",
+    "\n",
+    "def add_noise(image):\n",
+    "    noise = np.random.normal(loc=0, scale=25, size=image.shape)\n",
+    "    noisy_image = cv2.add(image, noise.astype(np.uint8))\n",
+    "    return np.clip(noisy_image, 0, 255)\n",
+    "\n",
+    "def change_brightness(image, factor):\n",
+    "    return cv2.convertScaleAbs(image, alpha=factor, beta=0)\n",
+    "\n",
+    "def blur_image(image, kernel_size):\n",
+    "    return cv2.GaussianBlur(image, (kernel_size, kernel_size), 0)\n",
+    "\n",
+    "def evaluate_images(reference_image, images, model_name):\n",
+    "    matches = []\n",
+    "    for i, img in enumerate(images):\n",
+    "        try:\n",
+    "            result = DeepFace.verify(reference_image, img, model_name=model_name, enforce_detection=False)\n",
+    "            matches.append(result[\"verified\"])\n",
+    "        except Exception as e:\n",
+    "            print(f\"Ошибка с изображением номер {i}: {e}\")\n",
+    "            matches.append(False)\n",
+    "    return matches\n",
+    "\n",
+    "reference_image = cv2.imread(reference_image_path)\n",
+    "\n",
+    "if reference_image is None:\n",
+    "    raise ValueError(f\"Не удалось загрузить эталонное изображение: {reference_image_path}\")\n",
+    "\n",
+    "images = []\n",
+    "for img_name in os.listdir(image_dir):\n",
+    "    if img_name.endswith('.JPG') or img_name.endswith('.jpg'):\n",
+    "        img_path = os.path.join(image_dir, img_name)\n",
+    "        img = cv2.imread(img_path)\n",
+    "        if img is not None:\n",
+    "            images.append(img)\n",
+    "        else:\n",
+    "            print(f\"Не удалось загрузить изображение: {img_path}\")\n",
+    "\n",
+    "if not images:\n",
+    "    raise ValueError(\"Не удалось загрузить изображения из директории.\")\n",
+    "\n",
+    "results = []\n",
+    "\n",
+    "for model in models:\n",
+    "    original_matches = evaluate_images(reference_image, images, model)\n",
+    "    original_recall = recall_score([1]*len(original_matches), original_matches)\n",
+    "    \n",
+    "    rotated_45 = [rotate_image(img, 45) for img in images]\n",
+    "    recall_45 = recall_score([1]*len(rotated_45), evaluate_images(reference_image, rotated_45, model))\n",
+    "    \n",
+    "    rotated_90 = [rotate_image(img, 90) for img in images]\n",
+    "    recall_90 = recall_score([1]*len(rotated_90), evaluate_images(reference_image, rotated_90, model))\n",
+    "    \n",
+    "    noisy_images = [add_noise(img) for img in images]\n",
+    "    recall_noise = recall_score([1]*len(noisy_images), evaluate_images(reference_image, noisy_images, model))\n",
+    "    \n",
+    "    bright_images_up = [change_brightness(img, 1.5) for img in images]\n",
+    "    recall_bright_up = recall_score([1]*len(bright_images_up), evaluate_images(reference_image, bright_images_up, model))\n",
+    "    \n",
+    "    bright_images_down = [change_brightness(img, 0.5) for img in images]\n",
+    "    recall_bright_down = recall_score([1]*len(bright_images_down), evaluate_images(reference_image, bright_images_down, model))\n",
+    "    \n",
+    "    blurred_images = [blur_image(img, 5) for img in images]\n",
+    "    recall_blur = recall_score([1]*len(blurred_images), evaluate_images(reference_image, blurred_images, model))\n",
+    "    \n",
+    "    results.append([\n",
+    "        model,\n",
+    "        original_recall,\n",
+    "        recall_45, \n",
+    "        recall_90,\n",
+    "        recall_noise,\n",
+    "        recall_bright_up,\n",
+    "        recall_bright_down,\n",
+    "        recall_blur\n",
+    "    ])\n",
+    "\n",
+    "df_results = pd.DataFrame(\n",
+    "    results, \n",
+    "    columns=[\n",
+    "        'Метод', \n",
+    "        'Исходный набор', \n",
+    "        'РџРѕРІРѕСЂРѕС‚ РЅР° 45В°', \n",
+    "        'РџРѕРІРѕСЂРѕС‚ РЅР° 90В°', \n",
+    "        'Изображение с шумом',\n",
+    "        'Увеличенная яркость',\n",
+    "        'Уменьшенная яркость',\n",
+    "        'Размытие'\n",
+    "    ]\n",
+    ")\n",
+    "print(df_results)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4d4e15a8-aa3c-454a-8aba-c65a29bda5ec",
+   "metadata": {},
+   "source": [
+    "#Задание 3. Часть 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1e002360-3c96-4393-8cc1-e5e68bedcb8b",
+   "metadata": {},
+   "source": [
+    "В данном задании предлагается рассмотреть задачу распознавания лиц как задачу классификации для оценки точности.\n",
+    "Вам даны [видео](https://drive.google.com/drive/folders/1z_YCdJF2Rf9WzlNSY3BpNFiakNisq5VB?usp=sharing), для которых представлена разметка в виде тайм-кодов и база фотографий людей с этих видео.\n",
+    "Необходимо взять каждый 50-й кадр видео (способ разбиения на кадры с учётом разметки - на ваше усмотрение) и для полученного набора изображений оценить метрику Precision на данном наборе изображений для всех лиц, присутствующих на видео и в разметке.\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "3b20127c-94a4-41b9-9971-66f92346ca32",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "2025-02-01 09:08:30.181388: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
+      "2025-02-01 09:08:30.191264: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
+      "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
+      "E0000 00:00:1738390110.202245  179413 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
+      "E0000 00:00:1738390110.205594  179413 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
+      "2025-02-01 09:08:30.217277: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
+      "To enable the following instructions: AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
+      "W0000 00:00:1738390111.407309  179413 gpu_device.cc:2344] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n",
+      "Skipping registering GPU devices...\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Видео: palmasizade_video.mp4, Recall: 0.1489\n",
+      "Средний Recall для всех видео: 0.1489\n"
+     ]
+    }
+   ],
+   "source": [
+    "import os\n",
+    "import cv2\n",
+    "import pandas as pd\n",
+    "from deepface import DeepFace\n",
+    "\n",
+    "def time_to_frame(time_str, fps):\n",
+    "    \"\"\"Преобразует строку времени формата 'HH:MM:SS' в номер кадра.\"\"\"\n",
+    "    time_parts = time_str.split(':')\n",
+    "    if len(time_parts) == 3:\n",
+    "        hours, minutes, seconds = map(float, time_parts)\n",
+    "    else:\n",
+    "        raise ValueError(\"Формат времени должен быть 'HH:MM:SS'\")\n",
+    "    \n",
+    "    total_seconds = hours * 3600 + minutes * 60 + seconds\n",
+    "    return int(total_seconds * fps)\n",
+    "\n",
+    "def get_labeled_persons_for_frame(labels, frame_number):\n",
+    "    \"\"\"Возвращает список лиц, присутствующих на данном фрейме, исходя из разметки.\"\"\"\n",
+    "    for start, end, persons in labels:\n",
+    "        if start <= frame_number <= end:\n",
+    "            return persons\n",
+    "    return []\n",
+    "\n",
+    "def extract_labels(df, fps):\n",
+    "    \"\"\"Извлекает и преобразует метки из CSV-файла в формат, пригодный для поиска лиц.\"\"\"\n",
+    "    labels = [\n",
+    "        (time_to_frame(row['from'], fps), time_to_frame(row['to'], fps), row['persons'].replace(',', ' ').split())\n",
+    "        for _, row in df.iterrows()\n",
+    "    ]\n",
+    "    return labels\n",
+    "\n",
+    "def match_verified(frame, person_photos_path):\n",
+    "    \"\"\"Проверяет, есть ли в текущем кадре изображение указанного человека.\"\"\"\n",
+    "    if not os.path.exists(person_photos_path):\n",
+    "        return False\n",
+    "\n",
+    "    for filename in os.listdir(person_photos_path):\n",
+    "        image_path = os.path.join(person_photos_path, filename)\n",
+    "        try:\n",
+    "            result = DeepFace.verify(image_path, frame, enforce_detection=False)\n",
+    "            if result['verified']:\n",
+    "                return True\n",
+    "        except Exception:\n",
+    "            continue\n",
+    "\n",
+    "    return False\n",
+    "\n",
+    "def evaluate_frame(frame, frame_number, labels, photos_dir):\n",
+    "    \"\"\"Оценивает текущий кадр для всех меток и возвращает количество верных и неверных сопоставлений.\"\"\"\n",
+    "    labeled_persons = get_labeled_persons_for_frame(labels, frame_number)\n",
+    "    tp, fn = 0, 0\n",
+    "\n",
+    "    for person in labeled_persons:\n",
+    "        person_photos_path = os.path.join(photos_dir, person)\n",
+    "        if match_verified(frame, person_photos_path):\n",
+    "            tp += 1\n",
+    "        else:\n",
+    "            fn += 1\n",
+    "\n",
+    "    return tp, fn\n",
+    "\n",
+    "def process_video(video_path, labels_path, photos_dir):\n",
+    "    \"\"\"Обрабатывает видео, возвращая количество истинных и ложных совпадений.\"\"\"\n",
+    "    cap = cv2.VideoCapture(video_path)\n",
+    "    df = pd.read_csv(labels_path)\n",
+    "    fps = cap.get(cv2.CAP_PROP_FPS)\n",
+    "\n",
+    "    labels = extract_labels(df, fps)\n",
+    "    tp_total, fn_total = 0, 0\n",
+    "    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
+    "    frame_number = 0\n",
+    "\n",
+    "    while frame_number < total_frames:\n",
+    "        ret, frame = cap.read()\n",
+    "        if not ret:\n",
+    "            break\n",
+    "\n",
+    "        tp, fn = evaluate_frame(frame, frame_number, labels, photos_dir)\n",
+    "        tp_total += tp\n",
+    "        fn_total += fn\n",
+    "\n",
+    "        frame_number += 50\n",
+    "        cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)\n",
+    "\n",
+    "    cap.release()\n",
+    "    return tp_total, fn_total\n",
+    "\n",
+    "def calculate_recall(tp, fn):\n",
+    "    return tp / (tp + fn) if (tp + fn) > 0 else 0\n",
+    "\n",
+    "def main(videos_dir, labels_dir, photos_dir):\n",
+    "    overall_recalls = []\n",
+    "\n",
+    "    for video_filename in os.listdir(videos_dir):\n",
+    "        if not video_filename.lower().endswith('.mp4'):\n",
+    "            continue\n",
+    "\n",
+    "        video_path = os.path.join(videos_dir, video_filename)\n",
+    "        labels_path = os.path.join(labels_dir, os.path.splitext(video_filename)[0] + \".csv\")\n",
+    "\n",
+    "        tp, fn = process_video(video_path, labels_path, photos_dir)\n",
+    "        recall = calculate_recall(tp, fn)\n",
+    "        \n",
+    "        overall_recalls.append(recall)\n",
+    "        print(f\"Видео: {video_filename}, Recall: {recall:.4f}\")\n",
+    "\n",
+    "    if overall_recalls:\n",
+    "        average_recall = sum(overall_recalls) / len(overall_recalls)\n",
+    "        print(f\"Средний Recall для всех видео: {average_recall:.4f}\")\n",
+    "\n",
+    "\n",
+    "\n",
+    "\n",
+    "\n",
+    "\n",
+    "videos_dir = \"task3/videos\"\n",
+    "labels_dir = \"task3/labels\"\n",
+    "photos_dir = \"task3/photos\"\n",
+    "main(videos_dir, labels_dir, photos_dir)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3d113f6f-697c-4e69-9680-88e2b568c68a",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python un",
+   "language": "python",
+   "name": "un"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.10.16"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
-- 
GitLab