فهرست منبع

Применены правки, собран pdf

Вадим Королёв 3 روز پیش
والد
کامیت
b21c0ef01c
3فایلهای تغییر یافته به همراه2686 افزوده شده و 75 حذف شده
  1. 12 0
      pdf/Наклейка.pdf
  2. 1574 0
      pdf/Пояснительная записка.pdf
  3. 1100 75
      Пояснительная записка.odt

+ 12 - 0
pdf/Наклейка.pdf

@@ -0,0 +1,12 @@
+ПОЯСНИТЕЛЬНАЯ ЗАПИСКА
+
+К ДИПЛОМНОМУ ПРОЕКТУ
+                 ПО
+
+СПЕЦИАЛЬНОСТИ 09.02.07
+  СТУДЕНТА ГРУППЫ 4ИС
+
+          Королёва В.С.
+
+                 2025
+

+ 1574 - 0
pdf/Пояснительная записка.pdf

@@ -0,0 +1,1574 @@
+              МИНИСТЕРСТВО ОБРАЗОВАНИЯ
+                     КИРОВСКОЙ ОБЛАСТИ
+
+Кировское областное государственное профессиональное
+           образовательное бюджетное учреждение
+
+       “Вятско-Полянский механический техникум”
+                         (КОГПОБУ ВПМТ)
+
+СОГЛАСОВАНО              ДОПУСТИТЬ К ЗАЩИТЕ
+
+Председатель цикловой    Заместитель директора
+методической комиссии    по УР
+
+_______ А.А.Гарифова           _______Н.В. Шешегова
+    __.__.__             __.__.__
+
+ДИПЛОМНЫЙ ПРОЕКТ
+
+      ДП. 012 . 09.02.07. 000 . ПЗ
+
+Консультант по                  Руководитель проекта
+внедрению ИС
+__________С.А.Пивоваров          ______С. А. Пивоваров
+__.__.__                         __.__.__
+
+Нормоконтроль                     Разработал
+_______Е.А. Новикова     ____В. С. Королёв
+__.__.__
+                                ___.___.___
+Рецензент
+______ Е.В. Галимова
+__.__.__
+                                                        СОДЕРЖАНИЕ
+Введение................................................................................................................................................ 3
+Основная часть..................................................................................................................................... 4
+
+   1 Постановка задачи автоматизации..............................................................................................4
+   2 Проектирование информационной системы.............................................................................. 6
+   3 Разработка пользовательского интерфейса информационной системы..................................8
+   4 Анализ разработанной информационной системы, выявление достоинств и недостатков 14
+   5 Разработка методики внедрения и сопровождения информационной системы...................15
+Заключение..........................................................................................................................................18
+Список использованных источников................................................................................................ 19
+Приложение А.....................................................................................................................................20
+Приложение Б..................................................................................................................................... 21
+Приложение В..................................................................................................................................... 22
+Приложение Г..................................................................................................................................... 23
+Приложение Д.....................................................................................................................................30
+Приложение Ж.................................................................................................................................... 37
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                   СОДЕРЖАНИЕ  Лит.  Лист  Листов
+                                                                  1
+                                                         1
+
+Н. Контр.  Новикова                                      ВПМТ 4ИС
+Утверд.    Галимова
+                                                    ВВЕДЕНИЕ
+
+        Актуальность темы: поиск фотографий в медиатеке на которых запечатлен
+определённый студент может занять большое время, особенно если общее количество
+фотографий исчисляется тысячами. Проект стремится решить эту проблему, автоматируя
+ручной процес.
+
+        Цель и задачи: разработать систему для поиска фотографий, на которых запечатлено
+лицо пользователя. Система должна иметь возможность сохранить результаты поиска
+удобным для пользователя способом.
+
+        Объект исследования: создание биометрического слепка по загруженной фотографии
+пользоваеля, поиск подобной биометрии по сформированной базе данных, формирование
+архива, сохранение результата на флеш-накопитель пользователя.
+
+        Предмет исследования: процесс распознавания и сравнения лиц, сохранение
+результата.
+
+        Структура работы:
+        1 Постановка задачи автоматизации;
+        2 Проектирование информационной системы;
+        2 Разработка пользовательского интерфейса информационной системы;
+        4 Анализ разработанной информационной системы, выявление достоинств и
+недостатков;
+        5 Разработка методики внедрения и сопровождения информационной системы.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                   ВВЕДЕНИЕ  Лит.  Лист    Листов
+                                                                  1
+                                                       1
+
+Н. Контр.  Новикова                                    ВПМТ 4ИС
+Утверд.    Галимова
+                                             ОСНОВНАЯ ЧАСТЬ
+
+        1 Постановка задачи автоматизации
+
+        1.1 Задачи системы:
+
+        - Обработка медиатеки техникума, поиск и идентификация лиц, найденных на
+фотографиях;
+
+        - Получение фото пользователя, распознавание полученного снимка;
+        - Формирование списка распознанных фотографий, известных системе, на которых
+запечатлен пользователь;
+        - Сохранение результата работы системы на флеш-накопитель.
+
+        1.2 Входные данные:
+
+        - Фотографии в медиатеке техникума;
+        - Фотография лица пользователя.
+
+        1.3 Выходные данные:
+
+        Файл архива в формате zip, содержащий фотографии, на которых запечатлен
+пользователь.
+
+        1.4 Возможные изменения информационных потребностей пользователей:
+
+        - Сбор не только фотографий, но и видео;
+        - Сохранение результата не только на внешний накопитель, но и отправка на
+электронную почту.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                   Постановка задачи  Лит.  Лист  Листов
+                                         автоматизации                   2
+                                                                1
+
+Н. Контр.  Новикова                                             ВПМТ 4ИС
+Утверд.    Галимова
+           1.5 Алгоритм решения задачи:
+
+        1.5.1 Разработать структуру базы данных для сопоставления одного лица множеству и
+быстрой выборке файлов фотографий;
+
+        1.5.2 Разработать программу, работающую в фоновом режиме, которая обрабатывает
+фотографии, выполняет анонимную идентификацию всех найденных лиц и сохраняет
+информацию в базу данных;
+
+        1.5.3 Разработать графический интерфейс, предназначенный для взаимодействия
+пользователей с системой, позволяющий сфотографировать лицо пользователя, отправить
+его на обработку в систему и получить результат;
+
+        1.5.4 Разработать механизм, позволяющий пользователям сохранять результат работы
+системы.
+
+        С системой взаимодействует два типа пользователей — студенты, которые хотят
+получить результат работы и администратор, который может взаимодействовать с
+механизмом сканирования фотографий системы.
+
+           1.6 Похожие проекты и их сравнение
+
+        В ходе изучения предметной области были проанализрованы похожие решения,
+выявлены достоинства и недостатки (таблица 1.1).
+
+           Таблица 1.1 — Описание похожих проектов
+
+Проект                   Достоинства                   Недостатки
+
+Сбор       изображений   Интеграция                 с  Не          самостоятельное
+
+студентов и сотрудников  корпоративным                 приложение, а адаптер
+
+МИЭМ [1]                 мессенджером.                 mongodb.
+
+Google Photos [2],       Точное распознавание лиц,     Ограничение по размеру для
+Яндекс Диск [3]          облачная платформа.           некоммерческой версии, нет
+                                                       автоматической компоновки
+                                                       результата.
+
+                                                                                    Лист
+
+Изм. Лист  № докум.  Подпись Дата              ДП.012.09.02.07.000.П3                      2
+        2 Проектирование информационной системы
+
+        При проектировании системы были выделены два типа пользователей: студенты и
+администраторы, а так же определены функции, которые каждый из типов может
+использовать. Описание функций приведено в use-case диаграмме (рис. 2.1).
+
+                                Рисунок 2.1 — use-case диаграмма системы
+
+        При проектировании также была разработана диаграмма, отображающая основной
+бизнес процесс проекта. Диаграмма выполнена в нотации IDEF0 и приведена в приложении
+А.
+
+        Для эффективной обработки лиц потребовалось разработать базу данных, хранящую
+в себе уже распознанные лица студентов и пути к изображениям. Это решение позволяет не
+обрабатывать заново тысячи фотографий медиатеки, а вместо этого сравнить полученное
+лицо с гораздо меньшим количеством данных. Разработана диаграмма связей сущностей,
+приведена в приложении Б.
+
+        Для пояснения структуры данных был разработан словарь данных (приложение В).
+        Проанализировав альтернативные решения, были выявлены следующие общие
+характеристики:
+        - Использование искусственного интеллекта для распознавания лиц;
+        - Исполнение в браузере.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                   Проектирование          Лит.  Лист  Листов
+                                                                              2
+                                       информационной системы        1
+
+Н. Контр.  Новикова                                                  ВПМТ 4ИС
+Утверд.    Галимова
+           Таблица 2.1 — Параметры среды разработки
+
+Параметр                           Значение
+Распознавание лиц
+                                   Язык              программирования  python,
+Пользовательский интерфейс
+                                   библиотека face_recognition [4], так как
+
+                                   python имеет обширные средства работы с
+
+                                   искусственным интеллектом и обработкой
+
+                                   изображений.
+
+                                   Язык программирования javascript,
+                                   фреймворк vue.js [5], так как платформа
+                                   браузера, на которой исполняется код,
+                                   предоставляет много возможностей в плане
+                                   разработки интерфейса.
+
+                                                                                Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                       2
+        3 Разработка пользовательского интерфейса информационной системы
+
+        Пользовательский интерфейс разработан с помощью веб-технологий, таких как:
+        - HTML;
+        - CSS;
+        - JavaScript.
+        Типичный сценарий взаимодействия пользователя с системой:
+        1 Подойти к устройству, на котором развёрнут интерфейс;
+        Пользователю будут представлены краткие инструкции по работе с системой и кнопка
+«Начать» (рис. 3.1). Кнопка «Нажать» проверит, подключено ли внешнее хранилище, и, в
+случае если хранилище не подключено, выдаст ошибку с соответствующим сообщением
+(рис. 3). Проверка выполняется с помощью отправки HTTP запроса на API, работающее на
+том же устройстве, что и общий интерфейс. API собирает все устройства, подключенные к
+системе, имеющие тип «disk», а так же имеющие атрибут «removable» с помощью
+библиотеки pyudev и функции list_devices [6]. Затем, выполняется поиск всех разделов на
+этом устройстве, вычисляется точка монтирования. Если какой-либо шаг в этой
+последовательности был провален, система выдаёт ошибку подключения хранилища (рис.
+3.2). Пример кода, отвечающего за взаимодействие пользователя с системой приведены в
+листинга Ж.1 - Ж.3.
+
+                         Рисунок 3.1 — Начальная страница системы
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                             Разработка        Лит.  Лист  Листов
+                                            пользовательского                     5
+                                                                         1
+                                                интерфейса
+Н. Контр.  Новикова                    информационной системы            ВПМТ 4ИС
+Утверд.    Галимова
+       Рисунок 3.2 — Ошибка, сообщающая о том, что необходимо подключить внешнее
+                                                     хранилище
+
+        2 Подключить внешнее хранилище;
+        3 Сфотографироваться;
+        Система кодирует данные фотографии в base64, передаёт по сети в подсистему
+распознавания, где данные декодируются и загружаются в память. На странице отображён
+видеопоток для предпросмотра фотографии (рис. 3.3). Пример кода, управляющий работой с
+фотографиями приведён в листингах Ж.4-Ж.6.
+
+                                                           Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                               2
+                               Рисунок 3.3 — Страница снятия фотографии
+
+        4 Ждать процесса распознавания;
+        Распознавание занимает меньше двух секунд при тестовой выборке из 1000
+фотографий. Но, в случае если ожидание окажется слишком долгим, интерфейс системы
+будет отображать экран загрузки с одним случайно выбранным интересным фактом о
+техникуме (рис. 3.4).
+        Процесс распознавания заключается в расшифровке изображения, закодированного на
+предыдущем шаге. Изображение сохраняется во временный каталог системы, затем читается
+библиотекой face_recognition. После этого, библиотека ищет лица на фотографии. Если
+найдено больше или меньше одного лица, возвращается ошибка, в интерфейсе открывается
+экран с описанием ошибки (рис. 3.5). Экран позволяет перефотографироваться или
+вернуться на главный экран.
+        Система затем десериализует и загружает данные всех известных кодировок лиц из
+базы данных в память. Кодировка лиц представляет собой 128-размерный массив [7]. Массив
+сериализуется в последовательность байтов для сохранения в базе данных, и
+десериализуется обратно в массив при запросе пользователя.
+        Система проверяет кодировки лиц из базы данных с полученной, формирует выборку
+лиц, сортирует, выполняя поиск самого похожего лица. Далее, все фотографии, на которых
+это лицо было запечатлено, возвращаются в интерфейс для отображения и/или сохранения.
+
+                                                           Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                                3
+                     Рисунок 3.4 — Экран ожидания результатов
+
+                                Рисунок 3.5 — Экран с описанием ошибки
+
+        5 Просмотреть результат сборки фотографий;
+        На этом экране система отображает количество фотографий, которое было найдено, а
+так же выборку из результата в размере не более 6 фотографий (рис. 3.6). На экране
+расположены две кнопки: «На главную» и «Сохранить результат». Код страницы просмотра
+результата приведён в листинге Ж.7.
+
+                                                               Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                                 4
+                                Рисунок 3.6 — Экран просмотра результата
+
+        6 Сохранить результат работы системы.
+        Перед сохранением пользователю выдаётся предупреждение с информацией о
+сохранении файла (рис. 3.7). Имя файла генерируется динамически.
+
+                      Рисунок 3.7 — Предупреждение о сохранении фотографий
+
+        После подтверждения сохранения, система передаёт ID фотографий, которые нужно
+сохранить, формирует zip-архив, который скачивается и сохраняется на внешнем хранилище
+(рис. 3.8). Код, отвечающий за формирование zip-архива приведён в листинге Ж.8.
+
+                                                           Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                               5
+                     Рисунок 3.8 — Пример сохранения на внешнем носителе
+
+                                                                          Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                 6
+        4 Анализ разработанной информационной системы, выявление достоинств и
+недостатков
+
+        После завершения первой итерации проекта, была создана тестовая выборка
+фотографий, загруженных с сайта Вятско-Полянского механического техникума [7] в
+количестве 1000 файлов. Файлы были обработаны системой, проведено несколько тестов для
+проверки работоспособности системы. Тесты оказались успешными, для автора результат
+содержал 7 фотографий.
+
+        Разработанная система имеет как достоинства, так и недостатки.
+        Список достоинств:
+        - Точное распознавание лиц на фотографиях;
+        - Быстрая обработка данных;
+        - Гибкость в настройке;
+        - Простой интерфейс.
+        Список недостатков:
+        - Обязательно подключение USB-накопителя;
+        - Нет возможности отправить результат на электронную почту;
+        - Громоздкая архитектура проекта.
+        Использованная в проекте библиотека распознавания лиц позволяет не только
+распознавать лица, но и выявлять черты лица и выделять прямоугольник, который был
+определён как совпавшее лицо. В будущем возможно применение этого выделения как опция
+для пользователей.
+        Система может быть использована не только в образвательных учереждениях
+(школах, техникумах), но и в любой другой организации, ведущей медиатеку. Степень
+уникальности решения является довольно высокой, так как альтернативы предлагают
+обработку только в облаке, а так же не ведут базу данных лиц для распознавания.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                     Анализ разработанной   Лит.  Лист  Листов
+                                       информационной системы,                 1
+                                                                      1
+                                        выявление достоинств и
+Н. Контр.  Новикова                             недостатков           ВПМТ 4ИС
+Утверд.    Галимова
+        5 Разработка методики внедрения и сопровождения информационной системы
+
+        После разработки первой версии программного продукта, были разработаны
+руководство пользователя в соответствии с ГОСТ 19.505-79 [8] (приложение Г) и
+руководство администратора в соответствии с ГОСТ 34.201-2020 [9] (приложение Д).
+
+        Руководство пользователя описывает порядок работы с системой, а так же описания
+ошибок, которые выдаются системой и шаги для их исправления.
+
+        Руководство администратора описывает каким образом система работает, как её
+запускать, заполнять данными, а так же описания ошибок и шаги по исправлению.
+
+        5.1 Программа резервного копирования и восстановления
+
+        5.1.1 Oбщиe пoлoжeния
+
+        Нacтoящий рeглaмeнт прoвeдeния рeзeрвнoгo кoпирoвaния (вoccтaнoвлeния)
+прoгрaмм и дaнных, хрaнящихcя нa aвтoмaтизирoвaнных рaбoчих мecтaх и ceрвeрaх
+рaзрaбoтaн c цeлью:
+
+        - Oпрeдeлeния пoрядкa рeзeрвирoвaния дaнных для пocлeдующeгo вoccтaнoвлeния
+рaбoтocпocoбнocти инфoрмaциoннoй cиcтeмы пeрcoнaльных дaнных oргaнизaции при
+пoлнoй или чacтичнoй пoтeрe инфoрмaции, вызвaннoй cбoями или oткaзaми aппaрaтнoгo
+или прoгрaммнoгo oбecпeчeния, oшибкaми пoльзoвaтeлeй;
+
+        - Oпрeдeлeния пoрядкa вoccтaнoвлeния инфoрмaции в cлучae вoзникнoвeния тaкoй
+нeoбхoдимocти;
+
+        - Упoрядoчeния рaбoты дoлжнocтных лиц, cвязaннoй c рeзeрвным кoпирoвaниeм и
+вoccтaнoвлeниeм инфoрмaции.
+
+        В нacтoящeм дoкумeнтe рeглaмeнтируютcя дeйcтвия при выпoлнeнии cлeдующих
+мeрoприятий:
+
+        - Рeзeрвнoe кoпирoвaниe;
+        - Кoнтрoль рeзeрвнoгo кoпирoвaния;
+        - Хрaнeниe рeзeрвных кoпий;
+        - Пoлнoe или чacтичнoe вoccтaнoвлeниe дaнных и прилoжeний.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                       Разработка методики    Лит.  Лист  Листов
+                                       внедрения и сопровождения                 5
+                                        информационной системы          1
+
+Н. Контр.  Новикова                                                     ВПМТ 4ИС
+Утверд.    Галимова
+        Рeзeрвнoму кoпирoвaнию пoдлeжит инфoрмaция cлeдующих ocнoвных кaтeгoрий:
+        - Данные распознавания лиц на фотографиях;
+        - Связи данных лиц с фотографиями.
+
+        5.1.2 Пoрядoк рeзeрвнoгo кoпирoвaния
+
+        Cиcтeмa рeзeрвнoгo кoпирoвaния дoлжнa oбecпeчивaть прoизвoдитeльнocть,
+дocтaтoчную для coхрaнeния инфoрмaции, в уcтaнoвлeнныe cрoки и c зaдaннoй
+пeриoдичнocтью. Рeзeрвнoe кoпирoвaниe дoлжнo прoизвoдитьcя кaждый дeнь, рoвнo в 00:00
+пo Мocкoвcкoму врeмeни.
+
+        5.1.3 Кoнтрoль рeзультaтoв рeзeрвнoгo кoпирoвaния:
+
+        Кoнтрoль рeзультaтoв вceх прoцeдур рeзeрвнoгo кoпирoвaния ocущecтвляeтcя
+cиcтeмным aдминиcтрaтoрoм.
+
+        Нa прoтяжeнии пeриoдa врeмeни, кoгдa cиcтeмa рeзeрвнoгo кoпирoвaния нaхoдитcя в
+aвaрийнoм cocтoянии, дoлжнo ocущecтвлятьcя eжeднeвнoe кoпирoвaниe инфoрмaции,
+пoдлeжaщeй рeзeрвирoвaнию, c иcпoльзoвaниeм cрeдcтв фaйлoвых cиcтeм.
+
+        5.1.4 Вoccтaнoвлeниe инфoрмaции из рeзeрвнoй кoпии
+
+        В cлучae нeoбхoдимocти, вoccтaнoвлeниe дaнных из рeзeрвных кoпий прoизвoдитcя
+caмocтoятeльнo. Дeлaeтcя этo cлeдующим oбрaзoм: определить используемый файл базы
+данных .sqlite3, затем заменить файл резервной копией.
+
+        Перечень резервируемой информации:
+        - Копируемый ресурс: данные информационной системы;
+        - Метод копирования: бэкап данных с помощью средств планировщика ОС;
+        - Тип копирования: полное копирование;
+        - Тип носителя: внешнее файловое хранилище;
+        - Периодичность смены носителя: согласно технической документации
+установленного заводом изготовителем, либо после диагностики диска;
+        - Раписания копирования: раз в неделю;
+
+                                                           Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                                2
+           - Срок хранения: 3 месяца;
+           - Первичность проверки резервных копий: раз в месяц.
+           Методика настройки резервного копирования на сервере, приведена в приложении Д.
+
+           5.2 План мероприятий по внедрению и сопровождению информационной системы
+
+        Предлагаемый и рекомендуемый план мероприятий по внедрению информационной
+системы описан в таблице 5.1.
+
+           Таблица 5.1 — Рекомендуемый план мероприятий по внедрению
+
+№ Содержание работ                                 Оптимальное время на
+                                                   выполнение этапа
+1 Установить операционную систему на серверную     1 день
+       часть проекта, все зависимости проекта в
+       соответствии с README                       1 день
+
+2 Настроить веб-сервер на использование протокола  1 день
+       Hyper Text Markup Protocol Secure (HTTPS)
+                                                   2-3 дня
+3 Установить операционную систему на клиентскую
+       часть проекта, установить браузер           3-4 дня
+                                                   1 день
+4 Предоставить клиенту доступ к серверной части
+       проекта
+
+5 Загрузить изображения медиатеки в систему
+
+6 Протестировать корректность работы
+
+        При эксплуатации системы, компоненты, её составляющие должны быть обновлены
+до самой последней версии, не ломающей совместимость с существующим кодом. В случае
+если несовместимое обновление необходимо установить обязательно (например, обновление
+устраняет серьёзную проблему безопасности), необходимо обновить код в соответствии с
+установленной версией компонента.
+
+        При обновлении компонента системы, необходимо обновить версию в файле
+README репозитория проекта.
+
+                                                                                            Лист
+
+Изм. Лист  № докум.  Подпись Дата  ДП.012.09.02.07.000.П3                                   3
+                                                 ЗАКЛЮЧЕНИЕ
+
+        В ходе выполнения работы было проведено исследование существующих систем,
+разработан алгоритм работы, описан бизнес-процесс. На основании проектирования была
+разработана, внедрена и успешно протестирована система.
+
+        Разработка системы проходила в соответствии с требованиями системы и
+предполагаемыми желаниями будущих пользователей.
+
+        Система открыта для будущих улучшений, правок и добавления нового функционала.
+        Достоинства разработанной системы:
+        - API доступно для использования другими системами;
+        - Интерфейс простой и понятный;
+        - Точное распознавание лиц на фотографиях;
+        - Быстрая обработка данных;
+        - Гибкость в настройке.
+
+Изм. Лист      № докум.  Подпись Дата  ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                   ЗАКЛЮЧЕНИЕ  Лит.  Лист  Листов
+                                                                  1
+                                                         1
+
+Н. Контр.  Новикова                                      ВПМТ 4ИС
+Утверд.    Галимова
+                           СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
+
+           1 Сбор изображений студентов и сотрудников | МИЭМ Wiki [Электронный ресурс] —
+
+Режим доступа: https://wiki.miem.hse.ru/Projects/394/docs/photo-collecting-output. — Заглавие
+
+с экрана. — (Дата обращения: 02.05.2025).
+
+           2 Фото — Google Фото [Электронный ресурс] — Режим доступа:
+
+https://photos.google.com/. — Заглавие с экрана. — (Дата обращения: 02.05.2025).
+
+           3 Яндекс Диск [Электронный ресурс] — Режим доступа: https://360.yandex.ru/disk/. —
+
+Заглавие с экрана. — (Дата обращения: 02.05.2025).
+
+           4 ageitgey/face_recognition: The world's simplest facial recognition api for Python and the
+
+command              line  [Электронный    ресурс]  —    Режим                    доступа:
+
+https://github.com/ageitgey/face_recognition. — Заглавие с экрана. — (Дата обращения:
+
+02.05.2025).
+
+           5 Vue.js - The Progressive JavaScript Framework | Vue.js [Электронный ресурс] —
+
+Режим доступа: https://vuejs.org/. — Заглавие с экрана. — (Дата обращения: 02.05.2025).
+
+           6 User guide — pyudev 0.21.0 documentation [Электронный ресурс] — Режим доступа:
+
+https://pyudev.readthedocs.io/en/latest/guide.html#id4. — Заглавие с экрана. — (Дата
+
+обращения: 04.05.2025).
+
+           7 Вятско-Полянский механический техникум | Ваш шанс! Ваш успех! Ваше будущее!
+
+[Электронный ресурс] — Режим доступа: https://www.vpmt.ru/. — Заглавие с экрана. — (Дата
+
+обращения: 15.05.2025).
+
+           8 ГОСТ 19.505-79. Руководство оператора. Требования к содержанию и оформлению.
+
+Технические требования. — Введ. 1980-01-01.— М.: Государственный комитет СССР по
+
+стандартам, 2010.— 3 с.
+
+           9 ГОСТ 34.201-2020. Межгосударственный стандарт. Комплекс стандартов на
+
+автоматизированные системы. Виды, комплектность и обозначение документов при создании
+
+автоматизированных систем. Введ. 2022-01-01 - Издательство стандартов, 2020 - 12 с.
+
+Изм. Лист      № докум.    Подпись Дата    ДП.012.09.02.07.000.П3
+Разраб.    Королёв
+Провер.    Пивоваров                             СПИСОК  Лит.   Лист                     Листов
+                                         ИСПОЛЬЗОВАННЫХ                                     1
+                                                                1
+                                             ИСТОЧНИКОВ
+Н. Контр.  Новикова                                            ВПМТ 4ИС
+Утверд.    Галимова
+                      ПРИЛОЖЕНИЕ А
+                          (обязательное)
+
+Рисунок А.1 — Диаграмма основного бизнес-процесса
+                ПРИЛОЖЕНИЕ Б
+                   (обязательное)
+
+Рисунок Б.1 — Диаграмма связей сущностей
+                    ПРИЛОЖЕНИЕ В
+                       (обязательное)
+
+Таблица В.1 — Словарь данных сущности Photo
+
+Название    Тип     Пояснение                   Ограничения
+поля        данных
+id          int     Уникальный                  PRIMARY KEY, NOT
+                    идентификатор               NULL
+path        text    фотографии.
+                    Путь к фотографии в         UNIQUE
+                    медиатеке.
+
+Таблица В.2 — Словарь данных сущности Student
+
+Название    Тип     Пояснение                   Ограничения
+поля        данных
+                    Уникальный анонимный        PRIMARY KEY, NOT
+id          int     идентификатор студента.     NULL
+
+Таблица В.3 — Словарь данных сущности Face
+
+Название    Тип     Пояснение                   Ограничения
+поля        данных                              PRIMARY KEY, NOT
+id          int     Уникальный                  NULL
+encoding    blob    идентификатор лица.
+                                                FOREIGN KEY
+photo_id    int     Сериализованные данные      FOREIGN KEY
+                    лица. Исходные данные
+student_id  int     генерируются функцией
+                    face_encodings.
+
+                    Ссылается на фотографию,
+                    на которой запечатлено это
+                    лицо.
+
+                    Ссылается на студента,
+                    которому, как считает
+                    система, принадлежит
+                    данное лицо.
+                       ПРИЛОЖЕНИЕ Г
+                          (обязательное)
+
+ИНФОРМАЦИОННАЯ СИСТЕМА «ЛИЦО УСПЕХА»
+      МОДУЛЬ «ИНТЕРФЕЙС ПОЛЬЗОВАТЕЛЯ»
+             РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ
+                           ВЕРСИЯ 1.0
+
+                                2025
+                                          1 Введение
+
+        1.1 Область применения
+
+        Областью применения Модуля является взаимодействие пользователя с системой.
+
+        1.2 Краткое описание возможностей
+
+        Информационная система «Лицо успеха» предназначена для обработки медиатеки
+техникума, поиска и идентификации лиц, найденных на фотографиях.
+
+        В Модуле реализованы следующие возможности:
+    • Снятие фотографии пользователя;
+    • Автоматический поиск подключенных устройств внешнего хранения;
+    • Сохранение результата работы системы на внешнее хранилище.
+
+        1.3 Уровень подготовки пользователя
+
+        Пользователь должен иметь базовые навыки работы с компьютером.
+
+        1.4 Перечень эксплуатационной документации, с которой необходимо
+ознакомиться пользователю
+
+    • Настоящее Руководство.
+                         2 Назначение и условия применения
+
+        Модуль «Интерфейс пользователя» в составе системы «Лицо успеха»
+предназначен для предоставления возможности пользователю взаимодействовать с
+системой. В модуле реализована возможность снятия фотографии и сохранения
+результата работы системы.
+
+        Работа с Модулем доступна всем пользователям. Работа с Модулем доступна
+всегда, когда есть необходимость в получении или подаче информации.
+                                   3 Подготовка к работе
+
+        Для работы с системой «Лицо успеха» необходимо следующее аппаратное
+обеспечение:
+
+        • Внешнее хранилище данных, подключаемое по USB.
+        Система, на которой запущен интерфейс пользователя, должна иметь сенсорный
+экран и оборудована USB-камерой для возможности снятия фотографий.
+4 Описание операций
+
+4.1 Выполняемые функции и задачи
+
+        Модуль «Интерфейс пользователя» в составе системы «Лицо успеха» выполняет
+задачи, приведённые в таблице ниже:
+
+Таблица Г.1 — Описание функций и задач
+
+Задачи                              Описание
+Снятие фотографии
+                                    Пользователю предоставляется возможность
+Просмотр результата работы системы  снять фотографию своего лица, с живым
+                                    предпросмотром.
+Сохранение результата работы
+системы                             Пользователю предоставляется возможность
+                                    просмотреть результат работы системы.
+                                    Отображается до 6 фотографий.
+
+                                    Пользователю предоставляется возможность
+                                    сохранить результат работы системы на
+                                    внешнее хранилище. Хранилище должно
+                                    быть подключено перед началом работы
+                                    системы.
+
+        4.2 Описание операций технологического процесса обработки данных,
+необходимых для выполнения задач
+
+        Ниже приведено описание пользовательских операций для выполнения каждой из
+задач.
+
+        Задача: «Снятие фотографии»
+        Действия для выполнения:
+        1 Нажать на кнопку «Начать»;
+        2 Оставить своё лицо в кадре;
+        3 Нажать на кнопку «Сфотографироваться»;
+
+Задача: «Просмотр результата работы системы»
+Действия для выполнения:
+1 Сфотографироваться;
+2 Подождать от 2 до 10 секунд;
+3 Просмотреть результат.
+Задача «Сохранение результата работы системы»
+Действия для выполнения:
+1 Подключить внешнее хранилище;
+2 Сфотографироваться;
+3 Нажать на кнопку «Сохранить»;
+4 Подтвердить местоположение файла;
+5 Отключить внешнее хранилище.
+                       5 Аварийные ситуации
+
+        В случае возникновения ошибок при работе системы «Лицо успеха», не описанных
+ниже в данном разделе, необходимо обращаться к сотруднику подразделения технической
+поддержки, либо к ответственному Администратору системы «Лицо успеха».
+
+Таблица Г.2 — Описание аварийных ситуаций
+
+Ошибка                 Описание ошибки            Требуемые действия
+                                                  пользователя при
+USB хранилище не       Пользователь пытается      возникновении ошибки
+подключено             начать работу с системой,
+                       не подключив внешнее       Подключить в терминал
+На фотографии не       хранилище данных.          внешнее хранилище
+обнаружено ни одного                              данных (флешка, ssd
+лица                   Системе не удалось         накопитель)
+                       распознать ни одного лица
+На фотографии          на сделанной фотографии.   Принять другую позу
+обнаружено больше                                 лица, снять любые
+одного лица            Система распознала на      предметы одежды,
+Нет связанных с тобой  фотографии больше          закрывающие лицо.
+фотографий             одного лица.
+                                                  Оставьте в кадре только
+                       Система распознала         одно лицо.
+                       пользователя, но не нашла
+                       ни одной фотографии, на    -
+                       котором запечатлено его
+                       лицо.
+                       ПРИЛОЖЕНИЕ Д
+                          (обязательное)
+
+ИНФОРМАЦИОННАЯ СИСТЕМА «ЛИЦО УСПЕХА»
+                МОДУЛЬ «НЕЙРОДВИЖОК»
+
+          РУКОВОДСТВО АДМИНИСТРАТОРА
+                           ВЕРСИЯ 1.0
+
+                                2025
+                                                   Аннотация
+
+        Документ представляет руководство по сбору и обработке фотографий в медиатеке
+техникума с использованием системы распознавания лиц. Описаны основные
+возможности системы, такие как идентификация людей, ведение базы данных и
+развертывание HTTP API. Уровень подготовки пользователей требует базовых навыков
+работы с компьютером.
+
+        В разделе «Подготовка системы» указаны требования к программному
+обеспечению и шаги по настройке, включая сбор ресурсов интерфейса, настройку SSL,
+загрузку фотографий и запуск нейродвижка. Раздел "Аварийные ситуации" содержит
+информацию о возможных ошибках и рекомендации по их устранению. Документ служит
+справочным материалом для пользователей и администраторов системы.
+                                                   1 Введение
+
+        Область применения: сбор фотографий медиатеки техникума.
+        Краткое описание возможностей:
+    • Распознавание лиц на фотографиях;
+    • Идентификация людей на снимках, формирование выборки фотографий по снимку
+         пользователя;
+    • Ведение базы данных;
+    • Развертывание HTTP API для взаимодействия с системой.
+        Уровень подготовки пользователей: от пользователей требуются базовые знания
+работы с компьютером.
+        Перечень эксплуатационной информации:
+    • фреймворк для разработки api на языке программирования python - uvicorn
+         (https://www.uvicorn.org/)
+    • веб-сервер для развертывания интерфейса пользователя — apache
+         (https://apache.org/)
+    • установка ssl сертификата для apache (https://losst.pro/ustanovka-ssl-sertifikata-
+         apache-ot-lets-encrypt)
+2 Подготовка системы к работе
+
+        Система была протестирована, работает корректно в следующем окружении
+(таблица Д.1).
+
+        Таблица Д.1 — Версии компонентов  Версия
+Компонент                                 Ubuntu Linux, ядро 6.8.0-60-generic
+Операционная система                      x64
+Разрядность процессора                    Apache 2.4.58
+Веб-сервер                                3.12.3
+Версия python                             9.2.0
+Версия npm                                build-essential python3-venv libopenblas-
+Пакеты ОС                                 dev liblapack-dev net-tools
+                                          Firefox 137.0.2
+Веб-браузер
+
+        Версии пакетов python и node.js приведены репозиториях проекта и находятся по
+пути src/face-api/requirements.txt и src/web/package-lock.json соответственно.
+
+        Для запуска системы, требуется выполнить следующие действия:
+        1 Собрать все ресурсы пользовательского интерфейса в пакет с помощью команды
+npm run build, выгрузить пакет на веб-сервер. Пакет представляет собой папку (обычно
+создаётся под названием dist после выполнения команды).
+        2 Так как интерфейс системы запускается как сайт, то подключение должно быть
+защищено, так как некоторые возможности системы недоступны без безопасного
+контекста исполнения. Для создания защищённого соединения, потребуется настройка
+apache для работы с SSL сертификатами.
+        3 Загрузить фотографии в систему. За загрузку отвечает скрипт по пути src/face-
+api/scan-dir.py. Скрипт принимает как аргументы путь к базе данных (sqlite файл) и путь к
+папке, в которой хранятся фотографии. Скрипт рекурсивно собирает фотографии,
+распознаёт лица и загружает данные в систему.
+        4 Запустить нейродвижок. Команда для запуска нейродвижка должна быть похоже
+на что-то подобное:
+        uvicorn api:app --host 0.0.0.0 --port 8000 --ssl-keyfile <ПУТЬ К ФАЙЛУ .key> --ssl-
+certfile <ПУТЬ К ФАЙЛУ .pem>
+        5 Запустить файловое API на клиенте. Файловое API требуется для сохранения
+результата работы системы. Скрипт запуска расположен по пути src/file-api/start.sh.
+        Для проверки работы системы, необходимо открыть адрес, на котором развёрнут
+веб-сервер. Для проверки подключения внешнего хранилища, нужно нажать на кнопку
+«Начать». Если хранилище подключено, система покажет страницу снятия фотографии.
+Если система выдаёт результат слишком долго (больше 10 сек.), вероятнее всего, возникла
+проблема при запуске нейродвижка.
+
+        Резервное копирование должно осуществляться через программу cron.
+        В программу нужно ввести следующую запись (Каждый день в 2 часа ночи
+выполнять скрипт backup_sqlite.sh. Скрипт должен иметь права на выполнение.):
+        0 2 * * * /path/to/your/backup_sqlite.sh
+        В скрипт backup_sqlite поместить следующее:
+
+          #!/bin/bash
+          DATABASE="/путь/к/вашей/бд.db"
+          BACKUP_DIR="/путь/к/вашей/бэкап/папке"
+          DATE=$(date +"%Y-%m-%d")
+          BACKUP_FILE="$BACKUP_DIR/backup_$DATE.db"
+          cp "$DATABASE" "$BACKUP_FILE"
+          find "$BACKUP_DIR" -name "backup_*.db" -type f -mtime +7 -exec rm {} \;
+
+        Скрипт копирует файл базы данных в отдельную папку и добавляет к имени
+текущую дату. Затем скрипт удаляет файлы базы данных, старше чем 7 дней от текущей
+даты.
+3 Аварийные ситуации
+
+        В процессе эксплуатации системы, может произойти несколько видов аварийных
+ситуаций. Описания и шаги к исправлению описаны в таблице Д.2.
+
+Таблица Д.2 — Описание аварийных ситуаций
+
+Описание ошибки                          Шаги к исправлению
+При запросе проверки подключения USB
+хранилища, консоль браузера выдаёт       1 Проверить статус работы файлового
+сетевую ошибку.                          API;
+                                         2 Проверить адрес файлого API,
+При запросе к API нейродвижка, консоль   указанный в коде интерфейса
+браузера выдаёт сетевую ошибку.          пользователя. Исправить, если отличается
+                                         от текущего.
+Предпросмотр снимка лица не
+включается.                              1 Проверить статус работы API
+                                         нейродвижка;
+Порт уже занят (при запуске любого API)  2 Проверить адрес API нейродвижка,
+                                         исправить если отличается от текущего;
+                                         3 Убедиться, что API работает по
+                                         протоколу HTTPS. Если нет, то настроить
+                                         сертификаты HTTP веб-сервера, передать
+                                         их при запуске в API.
+
+                                         1 Проверить наличие и подключение
+                                         USB-камеры;
+                                         2 Убедиться, что интерфейс браузера
+                                         открыт в безопасном контексте (localhost
+                                         или через протокол HTTPS).
+
+                                         1 Определить процесс, использующий
+                                         занятый порт;
+                                         2 Если процесс критичный, запустить API
+                                         на другом порту, иначе завершить
+                                         блокирующий процесс.
+                        4 Описание сообщений
+
+        В процессе запуска или эксплуатации системы, может быть выдано множество
+сообщений об ошибках. В таблице Д.2 приведены описания сообщений и рекомендуемые
+действия при их получении.
+
+Таблица Д.2 — Описание сообщений
+
+Компонент системы       Сообщение                Рекомендуемые действия
+scan-dir.py
+                        Файл настроек по         Убедиться что по
+                        указанному пути не       указанному пути файл
+                        найден                   настроек существует
+
+                        Ключ настроек не найден  В файле настроек
+                                                 отсутствует требуемый
+                        Файл настроек содержит   ключ
+                        неверный JSON
+                                                 Исправить
+                        Не удалось открыть файл  форматирование файла
+                        базы данных              настроек
+
+                        Каталог не найден        Убедиться что путь к базе
+                                                 данных существует и есть
+                        Не обнаружено новых      права на его запись и
+                        изображений              чтение
+
+api.py                  Started server process   Убедиться что путь к
+Интерфейс пользователя  Finished server process  папке с фотографиями
+                                                 действительно существует
+                        На фотографии не
+                        обнаружено ни одного     - (не обработано ни одной
+                        лица                     отографии потому что
+                                                 новых изображений не
+                        На фотографии            найдено)
+                        обнаружено больше
+                        одного лица              - (api успешно запущено)
+
+                        Нет связанных с тобой    - (api успешно
+                        фотографий               выключено)
+
+                                                 Попробовать
+                                                 сфотографироваться,
+                                                 убрав с лица
+                                                 закрывающие его
+                                                 предметы
+
+                                                 Оставить в кадре только
+                                                 одно лицо
+
+                                                 - (фотографий не найдено)
+                        ПРИЛОЖЕНИЕ Ж
+                           (обязательное)
+
+Листинг Ж.1 — Разметка начальной страницы
+
+<script setup>
+// Стартовая страница
+
+import { createApp, h, ref }    from "vue"
+import { useRouter }            from 'vue-router'
+import { createConfirmDialog }  from 'vuejs-confirm-dialog'
+
+import Button           from "../components/Button.vue"
+import Heading          from "../components/Heading.vue"
+import Step             from "../components/Step.vue"
+import UsbNotConnected  from "../components/Modals/UsbNotConnected.vue"
+
+import config                   from "../config.js"
+
+import { checkExternalStorage} from "../api.js"
+
+const router = useRouter();
+
+function start() {
+       checkExternalStorage().then(function(data) {
+              const isOk = data.ok;
+
+if (isOk) {
+       router.push('/Camera');
+       return;
+
+}
+
+              // USB не подключен
+              const { reveal, onConfirm, onCancel } = createConfirmDialog(
+
+                     UsbNotConnected
+              );
+              reveal();
+              onConfirm(() => {
+
+                     // pass
+              });
+              onCancel(() => {
+
+                     // pass
+              });
+       });
+}
+          </script>
+
+          <template>
+                  <div id="mainPage" class="page-main">
+                         <Heading text="Лицо успеха"/>
+                         <p class="w3-center w3-xlarge">
+                                            Сфотографируйся, а программа найдёт все фотографии
+
+техникума, на которых ты присутствуешь!
+                         </p>
+                         <div class="steps">
+                                <Step
+                                       number="1"
+                                       text="Вставь флешку"
+                                       color="w3-red"
+                                       border-color="w3-border-pink"/>
+                                <Step
+                                       number="2"
+                                       text="Сфотографируйся"
+                                       color="w3-amber"
+                                       border-color="w3-border-orange"/>
+                                <Step
+                                       number="3"
+                                       text="Сохрани фотографии"
+                                       color="w3-yellow"
+                                       border-color="w3-border-amber"/>
+                         </div>
+
+                         <div class="w3-row">
+                                <div class="w3-container w3-col s12">
+                                       <Button
+                                               class="w3-block"
+                                               text="Начать"
+                                               stylename="primary"
+                                               icon="play"
+                                               @click="start"/>
+                                </div>
+
+                         </div>
+                  </div>
+          </template>
+
+          <style scoped>
+          #mainPage {
+
+                  grid-template-rows: auto auto auto 10vh;
+          }
+.steps {
+       margin: auto;
+
+}
+
+#modals {
+       position: absolute;
+       height: 100vh;
+       min-height: 100vh;
+       max-height: 100vh;
+       width: 100vw;
+       left: 0;
+       top: 0;
+       display: none;
+
+}
+</style>
+
+Листинг Ж.2 — api для использования в JavaScript
+
+// Связь с backend API, в Javascript функциях
+import config from "./config.js";
+
+//////////// API ЛИЦ ////////////
+// Посылает запрос на API лиц
+function doFaceFetch(path, params = {}) {
+
+       params.headers = {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+
+       };
+       return fetch(config.faceApiUrl + path, params);
+}
+
+// Отправляет лицо на обработку
+export async function sendFace(base64image) {
+
+       const response = await doFaceFetch("/accept-face", {
+              method: 'post',
+              body: JSON.stringify({base64image: base64image})
+
+       });
+       return await response.json();
+}
+
+// Посылает запрос на генерацию ZIP на сервере
+export async function getZip(imageIds) {
+
+       const response = await doFaceFetch("/zip", {
+              method: 'post',
+              body: JSON.stringify({imageIds: imageIds})
+       });
+       return await response.blob();
+}
+
+//////////// API ФАЙЛОВОЙ СИСТЕМЫ ////////////
+
+// Посылает запрос на API лиц
+function doFSFetch(path, params = {}) {
+
+       params.headers = {
+              'Accept': 'application/json',
+              'Content-Type': 'application/json'
+
+       };
+       return fetch(config.filesystemApiUrl + path, params);
+}
+
+// Запрашивает у сервера генерацию имени файла для сохранения
+export async function getFilenameToSave() {
+
+       if (config.disableUSBChecks) {
+              return {
+                     ok: true,
+                     path: "C:\\face_of_success\\result.zip"
+              };
+
+       }
+       const response = await doFSFetch("/get-name-to-save");
+       const jsonData = await response.json();
+       return jsonData;
+}
+
+// Запрашивает у сервера сохранение фотографий
+export async function requestSaving(zipBlob, path) {
+
+       if (config.disableUSBChecks) {
+              console.log("Сохранение файлов отключено");
+              return;
+
+       }
+       const fd = new FormData();
+       fd.append("zipfile", zipBlob);
+       fd.append("savepath", path);
+
+       await fetch(config.filesystemApiUrl + "/save", {
+              method: 'post',
+              body: fd
+
+       });
+          }
+
+          // Проверяет, подключено ли внешнее устройство хранения
+          export async function checkExternalStorage() {
+
+                  debugger;
+                  if (config.disableUSBChecks) {
+
+                         return {ok: true};
+                  }
+
+                      const response = await fetch(config.filesystemApiUrl + "/usb-
+connected");
+
+                  const jsonData = await response.json();
+                  return jsonData;
+          }
+
+Листинг Ж.3 — Модальное окно отображения ошибки о том, что USB-устройство
+
+не подключено.
+
+<script setup>  from "../Heading.vue"
+import Heading  from "../Button.vue"
+import Button
+
+const props = defineProps({filename: String});
+const emit = defineEmits(['confirm', 'cancel'])
+</script>
+
+          <template>
+                  <div class="w3-modal" style="display: block">
+                         <div class="w3-modal-content w3-animate-top">
+                                <div class="w3-container">
+                                       <div id="layout">
+                                               <Heading text="Хранилище не подключено"/>
+                                               <p class="w3-center w3-xlarge">
+                                                              Необходимо вставить в киоск флеш-карту или
+
+другое USB-хранилище.
+                                               </p>
+                                               <img class="w3-padding" src="/img/usb.png"/>
+                                                                           <Button icon="check" text="Хорошо"
+
+@click="emit('confirm')" stylename="secondary"/>
+                                       </div>
+
+                                </div>
+                         </div>
+                  </div>
+          </template>
+<style scoped>
+#layout
+{
+
+       display: grid;
+       grid-template-rows: auto auto 256px 10vh;
+}
+
+img
+{
+
+       width: auto;
+       margin: auto;
+       height: 100%;
+}
+</style>
+
+        Листинг Ж.4 — Разметка страницы снятия фотографии
+
+          <script setup>
+          // Страница снятия фотографии
+          // Помощь и немного кода:
+          //
+https://developer.mozilla.org/ru/docs/Web/API/Media_Capture_and_Streams_API/
+Taking_still_photos
+
+import { onMounted, ref }  from "vue"
+import { useRouter }       from 'vue-router'
+
+import Button         from "../components/Button.vue"
+import NavButton      from "../components/NavButton.vue"
+import Heading        from "../components/Heading.vue"
+
+import config         from "../config.js"
+
+import { storage } from '../storage.js'
+
+const video    = ref(null);
+const canvas   = ref(null);
+const router   = useRouter();
+
+function takePhoto() {
+
+const ctx               = canvas.value.getContext("2d");
+
+canvas.value.width = video.value.videoWidth;
+
+canvas.value.height = video.value.videoHeight;
+
+ctx.drawImage(video.value, 0, 0);
+                                   storage.photoData              =
+
+canvas.value.toDataURL("image/png").split(',')[1];
+
+       router.push('/Searching');
+}
+
+onMounted(() => {
+       navigator.mediaDevices
+              .getUserMedia({ video: true, audio: false })
+              .then((stream) => {
+                     video.value.srcObject = stream;
+                     video.value.play();
+              })
+              .catch((err) => {
+                     console.error(`An error occurred: ${err}`);
+              });
+
+})
+</script>
+
+<template>
+       <div id="cameraPage" class="page-main">
+              <Heading text="Улыбнись!"/>
+
+<div id="videoWrapper" class="w3-center w3-margin-bottom">
+       <video ref="video">Видеопоток недоступен</video>
+
+</div>
+
+<div class="w3-row">
+       <div class="w3-container w3-col s6">
+              <NavButton
+                     class="w3-block"
+                     text="Отмена"
+                     icon="xmark"
+                     target="Main"
+                     stylename="secondary"/>
+       </div>
+       <div class="w3-container w3-col s6">
+              <Button
+                     class="w3-block"
+                     icon="camera"
+                     text="Сфотографироваться"
+                     stylename="primary"
+                     @click="takePhoto"/>
+       </div>
+                         </div>
+                  </div>
+
+                  <canvas ref="canvas" class="w3-hide"></canvas>
+          </template>
+
+          <style scoped>
+          #cameraPage
+          {
+
+                  grid-template-rows: auto 1fr 10vh;
+          }
+
+          #videoWrapper
+          {
+
+                  background-color: black;
+          }
+
+          #videoWrapper > video
+          {
+
+                  height: 100%;
+                  margin: auto;
+          }
+          </style>
+
+        Листинг Ж.5 — Код принятия фотографии от интерфейса
+
+          # accept-face.py
+          # Загружает изображение, возвращает список из id студентов, которые
+были
+          # найдены в БД
+          # Выводит ответ в стандартный вывод в формате JSON
+          # Пример ошибки
+          #{
+          # "ok": false,
+          # "description": "Перефотографируйтесь"
+          #}
+          # Пример успеха
+          #{
+          # "ok": true,
+          # "photoIds": [1, 2, 3, 4]
+          #}
+          import logging
+          import face_recognition
+          import numpy as np
+import FaceCoding.FaceStorage as FaceStorage
+
+# Выводит ошибку в std
+def fail(message):
+
+       return {"ok": False, "description": message}
+
+def success(photoIds):
+       output = []
+       for item in photoIds:
+              output.append(item[0])
+       obj = {"ok": True, "photoIds": output}
+       return obj
+
+def process(dbManager, faceEncoding):
+       # Хранилище
+       storage = FaceStorage.FaceStorage()
+       allFaces = dbManager.getStudentFaces()
+       storage.fill(allFaces)
+
+       # Узнаём что это за студент
+       result = storage.compare(faceEncoding)
+       if not result.found:
+
+              return fail("Нет связанных с тобой фотографий")
+
+       # Собираем все фотографии, которые есть с этим студентом
+       photoIds = dbManager.getPhotosByStudentId(result.foundStudentId)
+       return success(photoIds)
+
+def accept(filename, db):
+       # Загрузка фотографии
+       image = face_recognition.load_image_file(filename)
+
+       # Поиск лиц
+       faceEncodings = face_recognition.face_encodings(image, model='cnn')
+       logging.info("Найдено лиц: {}".format(len(faceEncodings)))
+       if (len(faceEncodings) == 0):
+
+              return fail("На фотографии не обнаружено ни одного лица")
+       if (len(faceEncodings) > 1):
+
+              return fail("На фотографии обнаружено больше одного лица")
+       faceEncoding = faceEncodings[0]
+
+       return process(db, faceEncoding)
+Листинг Ж.6 — Код класса обработчика распознавания фотографий
+
+# face-storage.py
+import face_recognition
+import numpy as np
+import io
+
+class FaceSearchResult:
+       def __init__(self, found, foundStudentId=None):
+              self.found = found
+              self.foundStudentId = foundStudentId
+
+# Класс для хранения кодировок лиц и студентов в памяти
+class FaceStorage:
+
+       def __init__(self):
+              self.faces = []
+              self.ids = []
+
+        # Добавляет соответствие лица и студента
+        # array - numpy массив
+        # studentId - число, id студента
+        def add(self, array, studentId):
+
+               self.faces.append(array)
+               self.ids.append(studentId)
+
+                                  # Заполняет лица. allFaces -       результат  работы
+database.DB.getStudentFaces
+
+                  def fill(self, allFaces):
+                         for item in allFaces:
+                                byte_io = io.BytesIO(item[1])
+                                self.add(np.load(byte_io), item[0])
+
+faces,  def compare(self, encoding):
+                 # Список из булевых значений, где matches[i] будет True, если
+
+               # и соответственно ids[i] будет похоже на studentFace
+               matches = face_recognition.compare_faces(
+
+                      self.faces,
+                      encoding,
+                      tolerance=0.5
+               )
+
+        if not True in matches:
+               # Совпадений не найдено
+          return FaceSearchResult(False)
+
+          # Узнаём какие индексы совпали
+            matchedIndexes = [i for (i, matched) in enumerate(matches) if
+
+matched]
+
+          # {student id: сколько совпадений}
+          counts = {}
+          for i in matchedIndexes:
+
+                 studentId = self.ids[i]
+                 counts[studentId] = counts.get(studentId, 0) + 1
+
+          # Выбор студента с наибольшим количеством совпадений
+          finalStudentId = max(counts, key=counts.get)
+
+          return FaceSearchResult(True, finalStudentId)
+
+Листинг Ж.7 — Код страницы просмотра результата
+
+<script setup>
+
+// Страница результата
+
+import Button           from "../components/Button.vue"
+
+import NavButton        from "../components/NavButton.vue"
+
+import Heading          from "../components/Heading.vue"
+
+import ResultImage      from "../components/ResultImage.vue"
+
+import ShowFilename     from "../components/Modals/ShowFilename.vue"
+
+import { onMounted, createApp, h }  from "vue"
+import { createConfirmDialog }      from 'vuejs-confirm-dialog'
+import { useRouter }                from 'vue-router'
+import { storage }                  from '../storage.js'
+import { getFilenameToSave }        from '../api.js'
+
+const router = useRouter();
+
+async function start() {
+       const response = await getFilenameToSave();
+
+          const { reveal, onConfirm, onCancel } = createConfirmDialog(
+                 ShowFilename,
+                 {filename: response.path}
+
+          );
+          reveal();
+          onConfirm(() => {
+                         storage.savePath = response.path;
+                         router.push("/Saving");
+                  });
+                  onCancel(() => {
+                         console.log('pass');
+                  });
+          }
+          </script>
+
+          <template>
+                  <div id="resultsPage" class="page-main">
+                         <Heading text="Готово!"/>
+                                             <p class="no-margin w3-center w3-xlarge">Найдено
+
+{{storage.foundFaces.length}} фотографий!<br/>Вот некоторые из них:</p>
+
+                         <div class="images">
+                                <ResultImage
+                                       v-for="imageId in storage.foundFaces.slice(0,6)"
+                                       :imageId="imageId"
+                                       :key="imageId"/>
+
+                         </div>
+
+                         <div class="w3-row">
+                                <div class="w3-container w3-col s6">
+                                       <NavButton
+                                               class="w3-block"
+                                               icon="house"
+                                               text="На главную"
+                                               target="Main"
+                                               stylename="secondary"/>
+                                </div>
+                                <div class="w3-container w3-col s6">
+                                       <Button
+                                               class="w3-block"
+                                               icon="save"
+                                               text="Сохранить результат"
+                                               stylename="primary"
+                                               @click="start"/>
+                                </div>
+
+                         </div>
+                  </div>
+                  <div id="modals"></div>
+          </template>
+<style scoped>
+#resultsPage {
+
+       grid-template-rows: auto auto minmax(0, 1fr) 10vh;
+}
+
+.images {
+       width: 80%;
+       margin-left: auto;
+       margin-right: auto;
+       margin-top: 1rem;
+       margin-bottom: 1rem;
+       display: grid;
+       grid-template-columns: repeat(3, minmax(0, 1fr));
+       grid-template-rows: 1fr 1fr 1em;
+       grid-gap: 1rem;
+
+}
+
+.no-margin {
+       margin: 0;
+
+}
+</style>
+
+Листинг Ж.8 — Код упаковки фотографий в zip-архив
+
+# Возвращает zip файл
+@app.post("/zip")
+async def createZip(r: ZipRequest):
+
+       db = getDb()
+       photoPaths = db.getPathsByIds(r.imageIds)
+       db.close()
+
+       # Сохранение изображения во временный файл
+       # Генерируем путь к файлу
+       tmpDir = tempfile.gettempdir()
+       zipPath = os.path.join(tmpDir, 'bundle.zip')
+
+       # Запись ZIP файла
+       with zipfile.ZipFile(zipPath, "w") as z:
+
+              for row in photoPaths:
+                     z.write(row[0], os.path.basename(row[0]))
+
+       # Возвращаем на клиент zip файл
+       return FileResponse(zipPath)
+

+ 1100 - 75
Пояснительная записка.odt

@@ -4,9 +4,9 @@
 
 Оглавление
 
ВЕДЕНИЕ  3
ведение  3
 
СНОВНАЯ ЧАСТЬ  4
сновная часть  4
 
 1 Постановка задачи автоматизации  4
 
@@ -19,35 +19,42 @@
 достоинств и недостатков  14
 
 5 Разработка методики внедрения и сопровождения информационной
-системы  16
+системы  15
 
АКЛЮЧЕНИЕ  19
аключение  18
 
ПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ  22
писок использованных источников  19
 
РИЛОЖЕНИЕ А  23
риложение А  20
 
РИЛОЖЕНИЕ Б  26
риложение Б  21
 
РИЛОЖЕНИЕ В  28
риложение В  22
 
РИЛОЖЕНИЕ Г  29
риложение Г  23
 
РИЛОЖЕНИЕ Д  36
риложение Д  30
 
-Введение
-
-Актуальность темы: автоматизация сбора фотографий студентов из
-медиатеки техникума упростит процесс, сводя его к снимку лица
-студента.
+Приложение Ж  37
 
-Цель и задачи: разработать систему для обработки запросов на
-сбор фотографий из медиатеки, способную распознавать лица и
-искать соответствующие снимки в базе данных..
+Введение
 
-Объект исследования: распознавание лиц на фотографиях,
-сопоставление с запрошенным, сборка снимков в zip
-архив.
+Актуальность темы: поиск фотографий в медиатеке на которых
+запечатлен определённый студент может занять большое
+время, особенно если общее количество фотографий
+исчисляется тысячами. Проект стремится решить эту
+проблему, автоматируя ручной процес.
+
+Цель и задачи: разработать систему для поиска фотографий, на
+которых запечатлено лицо пользователя. Система должна иметь
+возможность сохранить результаты поиска удобным для
+пользователя способом.
+
+Объект исследования: создание биометрического слепка по
+загруженной фотографии пользоваеля, поиск подобной
+биометрии по сформированной базе данных, формирование
+архива, сохранение результата на флеш-накопитель
+пользователя.
 
 Предмет исследования: процесс распознавания и сравнения лиц,
 сохранение результата.
@@ -76,12 +83,12 @@
 - Обработка медиатеки техникума, поиск и идентификация лиц,
 найденных на фотографиях;
 
-- Фотографирование лица пользователя;
+- Получение фото пользователя, распознавание полученного снимка;
 
-- Формирование множества фотографий, известных системе, на
-которых запечатлен пользователь;
+- Формирование списка распознанных фотографий, известных
+системе, на которых запечатлен пользователь;
 
-- Сохранение результата работы системы.
+- Сохранение результата работы системы на флеш-накопитель.
 
 1.2 Входные данные:
 
@@ -230,7 +237,9 @@ HTTP 
 [6]. Затем, выполняется поиск всех разделов на этом устройстве,
 вычисляется точка монтирования. Если какой-либо шаг в этой
 последовательности был провален, система выдаёт ошибку
-подключения хранилища (рис. 3.2).
+подключения хранилища (рис. 3.2). Пример кода, отвечающего
+за взаимодействие пользователя с системой приведены в листинга
+Ж.1 - Ж.3.
 
 [-- Image: Image4 --]Рисунок 3.1 — Начальная страница системы
 
@@ -244,7 +253,8 @@ HTTP 
 Система кодирует данные фотографии в base64, передаёт по сети в
 подсистему распознавания, где данные декодируются и загружаются
 в память. На странице отображён видеопоток для предпросмотра
-фотографии (рис. 3.3).
+фотографии (рис. 3.3). Пример кода, управляющий работой с
+фотографиями приведён в листингах Ж.4-Ж.6.
 
 [-- Image: Image9 --]Рисунок 3.3 — Страница снятия фотографии
 
@@ -289,7 +299,8 @@ face_recognition. 
 которое было найдено, а так же выборку из результата в
 размере не более 6 фотографий (рис. 3.6). На экране
 расположены две кнопки: «На главную» и «Сохранить
-результат».
+результат». Код страницы просмотра результата приведён в
+листинге Ж.7.
 
 [-- Image: Image8 --]Рисунок 3.6 — Экран просмотра результата
 
@@ -305,7 +316,8 @@ face_recognition. 
 После подтверждения сохранения, система передаёт ID фотографий,
 которые нужно сохранить, формирует zip-архив, который
 скачивается и сохраняется на внешнем хранилище (рис.
-3.8).
+3.8). Код, отвечающий за формирование zip-архива приведён в
+листинге Ж.8.
 
 [-- Image: Image11 --]Рисунок 3.8 — Пример сохранения на внешнем
 носителе
@@ -357,8 +369,9 @@ face_recognition. 
 системы
 
 После разработки первой версии программного продукта, были
-разработаны руководство пользователя (приложение Г) и
-руководство администратора (приложение Д).
+разработаны руководство пользователя в соответствии с ГОСТ
+19.505-79 [8] (приложение Г) и руководство администратора в
+соответствии с ГОСТ 34.201-2020 [9] (приложение Д).
 
 Руководство пользователя описывает порядок работы с системой, а
 так же описания ошибок, которые выдаются системой и шаги для их
@@ -370,72 +383,68 @@ face_recognition. 
 
 5.1 Программа резервного копирования и восстановления
 
-Плaн рeзeрвнoгo кoпирoвaния инфoрмaциoннoй cиcтeмы:
+5.1.1 Oбщиe пoлoжeния
 
-5.1.1 Oбщиe пoлoжeния:
-
-5.1.1.1 Нacтoящий рeглaмeнт прoвeдeния рeзeрвнoгo кoпирoвaния
+Нacтoящий рeглaмeнт прoвeдeния рeзeрвнoгo кoпирoвaния
 (вoccтaнoвлeния) прoгрaмм и дaнных, хрaнящихcя нa
-aвтoмaтизирoвaнных рaбoчих мecтaх и ceрвeрaх
-рaзрaбoтaн c цeлью:
+aвтoмaтизирoвaнных рaбoчих мecтaх и ceрвeрaх рaзрaбoтaн
+c цeлью:
 
-5.1.1.1.1 Oпрeдeлeния пoрядкa рeзeрвирoвaния дaнных для
-пocлeдующeгo вoccтaнoвлeния рaбoтocпocoбнocти
-инфoрмaциoннoй cиcтeмы пeрcoнaльных дaнных oргaнизaции
-при пoлнoй или чacтичнoй пoтeрe инфoрмaции, вызвaннoй cбoями
-или oткaзaми aппaрaтнoгo или прoгрaммнoгo oбecпeчeния,
-oшибкaми пoльзoвaтeлeй;
+- Oпрeдeлeния пoрядкa рeзeрвирoвaния дaнных для пocлeдующeгo
+вoccтaнoвлeния рaбoтocпocoбнocти инфoрмaциoннoй cиcтeмы
+пeрcoнaльных дaнных oргaнизaции при пoлнoй или чacтичнoй
+пoтeрe инфoрмaции, вызвaннoй cбoями или oткaзaми aппaрaтнoгo
+или прoгрaммнoгo oбecпeчeния, oшибкaми пoльзoвaтeлeй;
 
-5.1.1.1.2 Oпрeдeлeния пoрядкa вoccтaнoвлeния инфoрмaции в cлучae
+- Oпрeдeлeния пoрядкa вoccтaнoвлeния инфoрмaции в cлучae
 вoзникнoвeния тaкoй нeoбхoдимocти;
 
-5.1.1.1.3 Упoрядoчeния рaбoты дoлжнocтных лиц, cвязaннoй c
-рeзeрвным кoпирoвaниeм и вoccтaнoвлeниeм инфoрмaции.
+- Упoрядoчeния рaбoты дoлжнocтных лиц, cвязaннoй c рeзeрвным
+кoпирoвaниeм и вoccтaнoвлeниeм инфoрмaции.
 
-5.1.1.2 В нacтoящeм дoкумeнтe рeглaмeнтируютcя дeйcтвия при
-выпoлнeнии cлeдующих мeрoприятий:
+В нacтoящeм дoкумeнтe рeглaмeнтируютcя дeйcтвия при выпoлнeнии
+cлeдующих мeрoприятий:
 
-5.1.1.2.1 Рeзeрвнoe кoпирoвaниe;
+- Рeзeрвнoe кoпирoвaниe;
 
-5.1.1.2.2 Кoнтрoль рeзeрвнoгo кoпирoвaния;
+- Кoнтрoль рeзeрвнoгo кoпирoвaния;
 
-5.1.1.2.3 Хрaнeниe рeзeрвных кoпий;
+- Хрaнeниe рeзeрвных кoпий;
 
-5.1.1.2.4 Пoлнoe или чacтичнoe вoccтaнoвлeниe дaнных и
-прилoжeний.
+- Пoлнoe или чacтичнoe вoccтaнoвлeниe дaнных и прилoжeний.
 
-5.1.1.3 Рeзeрвнoму кoпирoвaнию пoдлeжит инфoрмaция cлeдующих
-ocнoвных кaтeгoрий:
+Рeзeрвнoму кoпирoвaнию пoдлeжит инфoрмaция cлeдующих ocнoвных
+кaтeгoрий:
 
-5.1.1.3.1 Данные распознавания лиц на фотографиях;
+- Данные распознавания лиц на фотографиях;
 
-5.1.1.3.2 Связи данных лиц с фотографиями.
+- Связи данных лиц с фотографиями.
 
 5.1.2 Пoрядoк рeзeрвнoгo кoпирoвaния
 
-5.1.2.1 Cиcтeмa рeзeрвнoгo кoпирoвaния дoлжнa oбecпeчивaть
-прoизвoдитeльнocть, дocтaтoчную для coхрaнeния инфoрмaции,
-в уcтaнoвлeнныe cрoки и c зaдaннoй пeриoдичнocтью. Рeзeрвнoe
-кoпирoвaниe дoлжнo прoизвoдитьcя кaждый дeнь, рoвнo в 00:00
-пo Мocкoвcкoму врeмeни.
+Cиcтeмa рeзeрвнoгo кoпирoвaния дoлжнa oбecпeчивaть
+прoизвoдитeльнocть, дocтaтoчную для coхрaнeния
+инфoрмaции, в уcтaнoвлeнныe cрoки и c зaдaннoй
+пeриoдичнocтью. Рeзeрвнoe кoпирoвaниe дoлжнo
+прoизвoдитьcя кaждый дeнь, рoвнo в 00:00 пo
+Мocкoвcкoму врeмeни.
 
-5.1.3 Кoнтрoль рeзультaтoв рeзeрвнoгo кoпирoвaния
+5.1.3 Кoнтрoль рeзультaтoв рeзeрвнoгo кoпирoвaния:
 
-5.1.3.1 Кoнтрoль рeзультaтoв вceх прoцeдур рeзeрвнoгo
-кoпирoвaния ocущecтвляeтcя cиcтeмным aдминиcтрaтoрoм.
+Кoнтрoль рeзультaтoв вceх прoцeдур рeзeрвнoгo кoпирoвaния
+ocущecтвляeтcя cиcтeмным aдминиcтрaтoрoм.
 
-5.1.3.2 Нa прoтяжeнии пeриoдa врeмeни, кoгдa cиcтeмa рeзeрвнoгo
+Нa прoтяжeнии пeриoдa врeмeни, кoгдa cиcтeмa рeзeрвнoгo
 кoпирoвaния нaхoдитcя в aвaрийнoм cocтoянии, дoлжнo
-ocущecтвлятьcя eжeднeвнoe кoпирoвaниe инфoрмaции,
-пoдлeжaщeй рeзeрвирoвaнию, c иcпoльзoвaниeм cрeдcтв
-фaйлoвых cиcтeм.
+ocущecтвлятьcя eжeднeвнoe кoпирoвaниe инфoрмaции, пoдлeжaщeй
+рeзeрвирoвaнию, c иcпoльзoвaниeм cрeдcтв фaйлoвых cиcтeм.
 
 5.1.4 Вoccтaнoвлeниe инфoрмaции из рeзeрвнoй кoпии
 
-5.1.4.1 В cлучae нeoбхoдимocти, вoccтaнoвлeниe дaнных из
-рeзeрвных кoпий прoизвoдитcя caмocтoятeльнo. Дeлaeтcя этo
-cлeдующим oбрaзoм: определить используемый файл базы данных
-.sqlite3, затем заменить файл резервной копией.
+В cлучae нeoбхoдимocти, вoccтaнoвлeниe дaнных из рeзeрвных
+кoпий прoизвoдитcя caмocтoятeльнo. Дeлaeтcя этo cлeдующим
+oбрaзoм: определить используемый файл базы данных .sqlite3,
+затем заменить файл резервной копией.
 
 Перечень резервируемой информации:
 
@@ -458,6 +467,9 @@ c
 
 - Первичность проверки резервных копий: раз в месяц.
 
+Методика настройки резервного копирования на сервере, приведена
+в приложении Д.
+
 5.2 План мероприятий по внедрению и сопровождению информационной
 системы
 
@@ -481,7 +493,8 @@ c
 
 2
 
-Настроить веб-сервер на использование HTTPS
+Настроить веб-сервер на использование протокола Hyper Text
+Markup Protocol Secure (HTTPS)
 
 1 день
 
@@ -519,7 +532,7 @@ c
 с установленной версией компонента.
 
 При обновлении компонента системы, необходимо обновить версию в
-README.
+файле README репозитория проекта.
 
 ЗАКЛЮЧЕНИЕ
 
@@ -534,6 +547,18 @@ README.
 Система открыта для будущих улучшений, правок и добавления
 нового функционала.
 
+Достоинства разработанной системы:
+
+- API доступно для использования другими системами;
+
+- Интерфейс простой и понятный;
+
+- Точное распознавание лиц на фотографиях;
+
+- Быстрая обработка данных;
+
+- Гибкость в настройке.
+
 Список использованных источников
 
 1 Сбор изображений студентов и сотрудников | МИЭМ Wiki
@@ -570,6 +595,16 @@ https://pyudev.readthedocs.io/en/latest/guide.html#id4. 
 https://www.vpmt.ru/. — Заглавие с экрана. — (Дата обращения:
 15.05.2025).
 
+8 ГОСТ 19.505-79. Руководство оператора. Требования к содержанию
+и оформлению. Технические требования. — Введ. 1980-01-01.— М.:
+Государственный комитет СССР по стандартам, 2010.— 3 с.
+
+9 ГОСТ 34.201-2020. Межгосударственный стандарт. Комплекс
+стандартов на автоматизированные системы. Виды,
+комплектность и обозначение документов при создании
+автоматизированных систем. Введ. 2022-01-01 - Издательство
+стандартов, 2020 - 12 с.
+
 приложение а
 
 (обязательное)
@@ -739,6 +774,10 @@ FOREIGN KEY
 
 • Внешнее хранилище данных, подключаемое по USB.
 
+Система, на которой запущен интерфейс пользователя, должна
+иметь сенсорный экран и оборудована USB-камерой для
+возможности снятия фотографий.
+
 4 Описание операций
 ===================
 
@@ -906,6 +945,7 @@ USB 
 
 Перечень эксплуатационной информации:
 
+фреймворк для разработки api на языке программирования python -
 uvicorn (https://www.uvicorn.org/)
 
 веб-сервер для развертывания интерфейса пользователя — apache
@@ -995,6 +1035,36 @@ uvicorn api:app --host 0.0.0.0 --port 8000 --ssl-keyfile <
 (больше 10 сек.), вероятнее всего, возникла проблема при
 запуске нейродвижка.
 
+Резервное копирование должно осуществляться через программу
+cron.
+
+В программу нужно ввести следующую запись (Каждый день в 2 часа
+ночи выполнять скрипт backup_sqlite.sh. Скрипт должен иметь
+права на выполнение.):
+
+0 2 * * * /path/to/your/backup_sqlite.sh
+
+В скрипт backup_sqlite поместить следующее:
+
+#!/bin/bash
+
+DATABASE="/путь/к/вашей/бд.db"
+
+BACKUP_DIR="/путь/к/вашей/бэкап/папке"
+
+DATE=$(date +"%Y-%m-%d")
+
+BACKUP_FILE="$BACKUP_DIR/backup_$DATE.db"
+
+cp "$DATABASE" "$BACKUP_FILE"
+
+find "$BACKUP_DIR" -name "backup_*.db" -type f -mtime +7 -exec
+rm {} \;
+
+Скрипт копирует файл базы данных в отдельную папку и добавляет
+к имени текущую дату. Затем скрипт удаляет файлы базы данных,
+старше чем 7 дней от текущей даты.
+
 3 Аварийные ситуации
 
 В процессе эксплуатации системы, может произойти несколько
@@ -1110,3 +1180,958 @@ Finished server process
 
 - (фотографий не найдено)
 
+Приложение Ж
+
+(обязательное)
+
+Листинг Ж.1 — Разметка начальной страницы
+
+<script setup>
+
+// Стартовая страница
+
+import { createApp, h, ref } from "vue"
+
+import { useRouter } from 'vue-router'
+
+import { createConfirmDialog } from 'vuejs-confirm-dialog'
+
+import Button from "../components/Button.vue"
+
+import Heading from "../components/Heading.vue"
+
+import Step from "../components/Step.vue"
+
+import UsbNotConnected from
+"../components/Modals/UsbNotConnected.vue"
+
+import config from "../config.js"
+
+import { checkExternalStorage} from "../api.js"
+
+const router = useRouter();
+
+function start() {
+
+checkExternalStorage().then(function(data) {
+
+const isOk = data.ok;
+
+if (isOk) {
+
+router.push('/Camera');
+
+return;
+
+}
+
+// USB не подключен
+
+const { reveal, onConfirm, onCancel } = createConfirmDialog(
+
+UsbNotConnected
+
+);
+
+reveal();
+
+onConfirm(() => {
+
+// pass
+
+});
+
+onCancel(() => {
+
+// pass
+
+});
+
+});
+
+}
+
+</script>
+
+<template>
+
+<div id="mainPage" class="page-main">
+
+<Heading text="Лицо успеха"/>
+
+<p class="w3-center w3-xlarge">
+
+Сфотографируйся, а программа найдёт все фотографии техникума,
+на которых ты присутствуешь!
+
+</p>
+
+<div class="steps">
+
+<Step
+
+number="1"
+
+text="Вставь флешку"
+
+color="w3-red"
+
+border-color="w3-border-pink"/>
+
+<Step
+
+number="2"
+
+text="Сфотографируйся"
+
+color="w3-amber"
+
+border-color="w3-border-orange"/>
+
+<Step
+
+number="3"
+
+text="Сохрани фотографии"
+
+color="w3-yellow"
+
+border-color="w3-border-amber"/>
+
+</div>
+
+<div class="w3-row">
+
+<div class="w3-container w3-col s12">
+
+<Button
+
+class="w3-block"
+
+text="Начать"
+
+stylename="primary"
+
+icon="play"
+
+@click="start"/>
+
+</div>
+
+</div>
+
+</div>
+
+</template>
+
+<style scoped>
+
+#mainPage {
+
+grid-template-rows: auto auto auto 10vh;
+
+}
+
+.steps {
+
+margin: auto;
+
+}
+
+#modals {
+
+position: absolute;
+
+height: 100vh;
+
+min-height: 100vh;
+
+max-height: 100vh;
+
+width: 100vw;
+
+left: 0;
+
+top: 0;
+
+display: none;
+
+}
+
+</style>
+
+Листинг Ж.2 — api для использования в JavaScript
+
+// Связь с backend API, в Javascript функциях
+
+import config from "./config.js";
+
+//////////// API ЛИЦ ////////////
+
+// Посылает запрос на API лиц
+
+function doFaceFetch(path, params = {}) {
+
+params.headers = {
+
+'Accept': 'application/json',
+
+'Content-Type': 'application/json'
+
+};
+
+return fetch(config.faceApiUrl + path, params);
+
+}
+
+// Отправляет лицо на обработку
+
+export async function sendFace(base64image) {
+
+const response = await doFaceFetch("/accept-face", {
+
+method: 'post',
+
+body: JSON.stringify({base64image: base64image})
+
+});
+
+return await response.json();
+
+}
+
+// Посылает запрос на генерацию ZIP на сервере
+
+export async function getZip(imageIds) {
+
+const response = await doFaceFetch("/zip", {
+
+method: 'post',
+
+body: JSON.stringify({imageIds: imageIds})
+
+});
+
+return await response.blob();
+
+}
+
+//////////// API ФАЙЛОВОЙ СИСТЕМЫ ////////////
+
+// Посылает запрос на API лиц
+
+function doFSFetch(path, params = {}) {
+
+params.headers = {
+
+'Accept': 'application/json',
+
+'Content-Type': 'application/json'
+
+};
+
+return fetch(config.filesystemApiUrl + path, params);
+
+}
+
+// Запрашивает у сервера генерацию имени файла для сохранения
+
+export async function getFilenameToSave() {
+
+if (config.disableUSBChecks) {
+
+return {
+
+ok: true,
+
+path: "C:\\face_of_success\\result.zip"
+
+};
+
+}
+
+const response = await doFSFetch("/get-name-to-save");
+
+const jsonData = await response.json();
+
+return jsonData;
+
+}
+
+// Запрашивает у сервера сохранение фотографий
+
+export async function requestSaving(zipBlob, path) {
+
+if (config.disableUSBChecks) {
+
+console.log("Сохранение файлов отключено");
+
+return;
+
+}
+
+const fd = new FormData();
+
+fd.append("zipfile", zipBlob);
+
+fd.append("savepath", path);
+
+await fetch(config.filesystemApiUrl + "/save", {
+
+method: 'post',
+
+body: fd
+
+});
+
+}
+
+// Проверяет, подключено ли внешнее устройство хранения
+
+export async function checkExternalStorage() {
+
+debugger;
+
+if (config.disableUSBChecks) {
+
+return {ok: true};
+
+}
+
+const response = await fetch(config.filesystemApiUrl +
+"/usb-connected");
+
+const jsonData = await response.json();
+
+return jsonData;
+
+}
+
+Листинг Ж.3 — Модальное окно отображения ошибки о том, что
+USB-устройство не подключено.
+
+<script setup>
+
+import Heading from "../Heading.vue"
+
+import Button from "../Button.vue"
+
+const props = defineProps({filename: String});
+
+const emit = defineEmits(['confirm', 'cancel'])
+
+</script>
+
+<template>
+
+<div class="w3-modal" style="display: block">
+
+<div class="w3-modal-content w3-animate-top">
+
+<div class="w3-container">
+
+<div id="layout">
+
+<Heading text="Хранилище не подключено"/>
+
+<p class="w3-center w3-xlarge">
+
+Необходимо вставить в киоск флеш-карту или другое
+USB-хранилище.
+
+</p>
+
+<img class="w3-padding" src="/img/usb.png"/>
+
+<Button icon="check" text="Хорошо" @click="emit('confirm')"
+stylename="secondary"/>
+
+</div>
+
+</div>
+
+</div>
+
+</div>
+
+</template>
+
+<style scoped>
+
+#layout
+
+{
+
+display: grid;
+
+grid-template-rows: auto auto 256px 10vh;
+
+}
+
+img
+
+{
+
+width: auto;
+
+margin: auto;
+
+height: 100%;
+
+}
+
+</style>
+
+Листинг Ж.4 — Разметка страницы снятия фотографии
+
+<script setup>
+
+// Страница снятия фотографии
+
+// Помощь и немного кода:
+
+//
+https://developer.mozilla.org/ru/docs/Web/API/Media_Capture_and_Streams_API/Taking_still_photos
+
+import { onMounted, ref } from "vue"
+
+import { useRouter } from 'vue-router'
+
+import Button from "../components/Button.vue"
+
+import NavButton from "../components/NavButton.vue"
+
+import Heading from "../components/Heading.vue"
+
+import config from "../config.js"
+
+import { storage } from '../storage.js'
+
+const video = ref(null);
+
+const canvas = ref(null);
+
+const router = useRouter();
+
+function takePhoto() {
+
+const ctx = canvas.value.getContext("2d");
+
+canvas.value.width = video.value.videoWidth;
+
+canvas.value.height = video.value.videoHeight;
+
+ctx.drawImage(video.value, 0, 0);
+
+storage.photoData =
+canvas.value.toDataURL("image/png").split(',')[1];
+
+router.push('/Searching');
+
+}
+
+onMounted(() => {
+
+navigator.mediaDevices
+
+.getUserMedia({ video: true, audio: false })
+
+.then((stream) => {
+
+video.value.srcObject = stream;
+
+video.value.play();
+
+})
+
+.catch((err) => {
+
+console.error(`An error occurred: ${err}`);
+
+});
+
+})
+
+</script>
+
+<template>
+
+<div id="cameraPage" class="page-main">
+
+<Heading text="Улыбнись!"/>
+
+<div id="videoWrapper" class="w3-center w3-margin-bottom">
+
+<video ref="video">Видеопоток недоступен</video>
+
+</div>
+
+<div class="w3-row">
+
+<div class="w3-container w3-col s6">
+
+<NavButton
+
+class="w3-block"
+
+text="Отмена"
+
+icon="xmark"
+
+target="Main"
+
+stylename="secondary"/>
+
+</div>
+
+<div class="w3-container w3-col s6">
+
+<Button
+
+class="w3-block"
+
+icon="camera"
+
+text="Сфотографироваться"
+
+stylename="primary"
+
+@click="takePhoto"/>
+
+</div>
+
+</div>
+
+</div>
+
+<canvas ref="canvas" class="w3-hide"></canvas>
+
+</template>
+
+<style scoped>
+
+#cameraPage
+
+{
+
+grid-template-rows: auto 1fr 10vh;
+
+}
+
+#videoWrapper
+
+{
+
+background-color: black;
+
+}
+
+#videoWrapper > video
+
+{
+
+height: 100%;
+
+margin: auto;
+
+}
+
+</style>
+
+Листинг Ж.5 — Код принятия фотографии от интерфейса
+
+# accept-face.py
+
+# Загружает изображение, возвращает список из id студентов,
+которые были
+
+# найдены в БД
+
+# Выводит ответ в стандартный вывод в формате JSON
+
+# Пример ошибки
+
+#{
+
+# "ok": false,
+
+# "description": "Перефотографируйтесь"
+
+#}
+
+# Пример успеха
+
+#{
+
+# "ok": true,
+
+# "photoIds": [1, 2, 3, 4]
+
+#}
+
+import logging
+
+import face_recognition
+
+import numpy as np
+
+import FaceCoding.FaceStorage as FaceStorage
+
+# Выводит ошибку в std
+
+def fail(message):
+
+return {"ok": False, "description": message}
+
+def success(photoIds):
+
+output = []
+
+for item in photoIds:
+
+output.append(item[0])
+
+obj = {"ok": True, "photoIds": output}
+
+return obj
+
+def process(dbManager, faceEncoding):
+
+# Хранилище
+
+storage = FaceStorage.FaceStorage()
+
+allFaces = dbManager.getStudentFaces()
+
+storage.fill(allFaces)
+
+# Узнаём что это за студент
+
+result = storage.compare(faceEncoding)
+
+if not result.found:
+
+return fail("Нет связанных с тобой фотографий")
+
+# Собираем все фотографии, которые есть с этим студентом
+
+photoIds = dbManager.getPhotosByStudentId(result.foundStudentId)
+
+return success(photoIds)
+
+def accept(filename, db):
+
+# Загрузка фотографии
+
+image = face_recognition.load_image_file(filename)
+
+# Поиск лиц
+
+faceEncodings = face_recognition.face_encodings(image,
+model='cnn')
+
+logging.info("Найдено лиц: {}".format(len(faceEncodings)))
+
+if (len(faceEncodings) == 0):
+
+return fail("На фотографии не обнаружено ни одного лица")
+
+if (len(faceEncodings) > 1):
+
+return fail("На фотографии обнаружено больше одного лица")
+
+faceEncoding = faceEncodings[0]
+
+return process(db, faceEncoding)
+
+Листинг Ж.6 — Код класса обработчика распознавания фотографий
+
+# face-storage.py
+
+import face_recognition
+
+import numpy as np
+
+import io
+
+class FaceSearchResult:
+
+def __init__(self, found, foundStudentId=None):
+
+self.found = found
+
+self.foundStudentId = foundStudentId
+
+# Класс для хранения кодировок лиц и студентов в памяти
+
+class FaceStorage:
+
+def __init__(self):
+
+self.faces = []
+
+self.ids = []
+
+# Добавляет соответствие лица и студента
+
+# array - numpy массив
+
+# studentId - число, id студента
+
+def add(self, array, studentId):
+
+self.faces.append(array)
+
+self.ids.append(studentId)
+
+# Заполняет лица. allFaces - результат работы
+database.DB.getStudentFaces
+
+def fill(self, allFaces):
+
+for item in allFaces:
+
+byte_io = io.BytesIO(item[1])
+
+self.add(np.load(byte_io), item[0])
+
+def compare(self, encoding):
+
+# Список из булевых значений, где matches[i] будет True, если
+faces,
+
+# и соответственно ids[i] будет похоже на studentFace
+
+matches = face_recognition.compare_faces(
+
+self.faces,
+
+encoding,
+
+tolerance=0.5
+
+)
+
+if not True in matches:
+
+# Совпадений не найдено
+
+return FaceSearchResult(False)
+
+# Узнаём какие индексы совпали
+
+matchedIndexes = [i for (i, matched) in enumerate(matches) if
+matched]
+
+# {student id: сколько совпадений}
+
+counts = {}
+
+for i in matchedIndexes:
+
+studentId = self.ids[i]
+
+counts[studentId] = counts.get(studentId, 0) + 1
+
+# Выбор студента с наибольшим количеством совпадений
+
+finalStudentId = max(counts, key=counts.get)
+
+return FaceSearchResult(True, finalStudentId)
+
+Листинг Ж.7 — Код страницы просмотра результата
+
+<script setup>
+
+// Страница результата
+
+import Button from "../components/Button.vue"
+
+import NavButton from "../components/NavButton.vue"
+
+import Heading from "../components/Heading.vue"
+
+import ResultImage from "../components/ResultImage.vue"
+
+import ShowFilename from "../components/Modals/ShowFilename.vue"
+
+import { onMounted, createApp, h } from "vue"
+
+import { createConfirmDialog } from 'vuejs-confirm-dialog'
+
+import { useRouter } from 'vue-router'
+
+import { storage } from '../storage.js'
+
+import { getFilenameToSave } from '../api.js'
+
+const router = useRouter();
+
+async function start() {
+
+const response = await getFilenameToSave();
+
+const { reveal, onConfirm, onCancel } = createConfirmDialog(
+
+ShowFilename,
+
+{filename: response.path}
+
+);
+
+reveal();
+
+onConfirm(() => {
+
+storage.savePath = response.path;
+
+router.push("/Saving");
+
+});
+
+onCancel(() => {
+
+console.log('pass');
+
+});
+
+}
+
+</script>
+
+<template>
+
+<div id="resultsPage" class="page-main">
+
+<Heading text="Готово!"/>
+
+<p class="no-margin w3-center w3-xlarge">Найдено
+{{storage.foundFaces.length}} фотографий!<br/>Вот некоторые из
+них:</p>
+
+<div class="images">
+
+<ResultImage
+
+v-for="imageId in storage.foundFaces.slice(0,6)"
+
+:imageId="imageId"
+
+:key="imageId"/>
+
+</div>
+
+<div class="w3-row">
+
+<div class="w3-container w3-col s6">
+
+<NavButton
+
+class="w3-block"
+
+icon="house"
+
+text="На главную"
+
+target="Main"
+
+stylename="secondary"/>
+
+</div>
+
+<div class="w3-container w3-col s6">
+
+<Button
+
+class="w3-block"
+
+icon="save"
+
+text="Сохранить результат"
+
+stylename="primary"
+
+@click="start"/>
+
+</div>
+
+</div>
+
+</div>
+
+<div id="modals"></div>
+
+</template>
+
+<style scoped>
+
+#resultsPage {
+
+grid-template-rows: auto auto minmax(0, 1fr) 10vh;
+
+}
+
+.images {
+
+width: 80%;
+
+margin-left: auto;
+
+margin-right: auto;
+
+margin-top: 1rem;
+
+margin-bottom: 1rem;
+
+display: grid;
+
+grid-template-columns: repeat(3, minmax(0, 1fr));
+
+grid-template-rows: 1fr 1fr 1em;
+
+grid-gap: 1rem;
+
+}
+
+.no-margin {
+
+margin: 0;
+
+}
+
+</style>
+
+Листинг Ж.8 — Код упаковки фотографий в zip-архив
+
+# Возвращает zip файл
+
+@app.post("/zip")
+
+async def createZip(r: ZipRequest):
+
+db = getDb()
+
+photoPaths = db.getPathsByIds(r.imageIds)
+
+db.close()
+
+# Сохранение изображения во временный файл
+
+# Генерируем путь к файлу
+
+tmpDir = tempfile.gettempdir()
+
+zipPath = os.path.join(tmpDir, 'bundle.zip')
+
+# Запись ZIP файла
+
+with zipfile.ZipFile(zipPath, "w") as z:
+
+for row in photoPaths:
+
+z.write(row[0], os.path.basename(row[0]))
+
+# Возвращаем на клиент zip файл
+
+return FileResponse(zipPath)
+