# Библиотека для решения задач компьютерного зрения методами топологического анализа данных

## Назначение

Библиотека предоставляет инструменты, позволяющие без труда применять методы топологического
анализа данных к произвольному набору фотографий, а также снабжена смежными инструментами
для решения задач классификации и распознавания лиц.

## Установка и условия применения

Установка библиотеки возможна напрямую из индекса пакетов языка Python командой `pip install cv-tda`.
Основной пакет содержит все необходимые инструменты топологического анализа данных для извлечения
признаков из изображений.

Библиотека поставляется с четырьмя опциональными пакетами, предоставляющими методы для решения
задач классификации, распознавания лиц, сжатия и сегментации. Для их использования требуется
установить дополнительные зависимости соответственно командами `pip install cv-tda[classification]`,
`pip install cv-tda[facerecognition]`, `pip install cv-tda[autoencoder]` и `pip install cv-tda[segmentation]`.
Более того, для использования описанного в основной работе обучаемого метода векторизации диаграмм
устойчивости необходимо установить утилиту torchph версии 0.0.0 командой
`pip install git+https://github.com/c-hofer/torchph.git@master`.

Следует обратить внимание, что работа библиотеки гарантируется только при использовании
Python версии 3.10. Корректное функционирование всех методов при установке других версий
интерпретатора не гарантируется.

Ограничений в работоспособности  библиотеки на различных операционных системах не выявлено.

Требования к количеству ядер и частоте процессора не предъявляются, но уменьшение доступности
ресурса приведёт к увеличению времени работы большинства методов. Требования к объёму оперативной
памяти при использовании библиотеки зависят от количества и размера анализируемых изображений:
для обработки 60,000 цветных фотографий размера 48 x 48 требуется не менее 32 ГБ оперативной памяти.
Графический процессор для работы библиотеки не требуется, хотя и может быть использован
для ускорения работы отдельных функций.

## Программный интерфейс

### Алгоритм извлечения топологических признаков

Основным элементом библиотеки является класс `FeatureExtractor` пакета `topology`, реализующий
обобщённый алгоритм топологического анализа набора изображений.

Класс реализует интерфейс `TransformerMixin` библиотеки scikit-learn, таким образом предоставляя
три стандартных метода: `fit` для настройки (“обучения”) алгоритма на тренировочной выборке, 
`transform` для преобразования тестовой выборки и `fit_transform`, комбинирующий предыдущие два.

Входными данными этих методов является один numpy-массив, содержащий все изображения набора
со значениями пикселей в интервале [0; 1]. При работе с монохромными изображениями, массив
должен иметь три измерения: номер изображения, его высота и ширина соответственно. В случае
цветных изображений, RGB-каналы записываются последним (четвёртым) измерением. Работа с
изображениями в других форматах не поддержана.

Основными параметрами класса являются несколько значений:
1) `n_jobs` – максимальное количество одновременно выполняемых задач, степень параллелизации
вычислений. Стандартное значение (`-1`) соответствует использованию всех доступных ресурсов процессора.

2) `reduced` – флаг, указывающий, какую версию алгоритма использовать: сокращённую (`True`)
или полную (`False`). Подробное описание обоих методов представлено в основной работе.

3) `return_diagrams` – флаг, при указании которого алгоритм вернёт не итоговые признаки,
а диаграммы устойчивости.

Выходными данными алгоритма при отсутствии параметра `return_diagrams` является двумерный
numpy-массив, содержащий признаковое описание для каждого изображения из исходного набора.
При указании параметра `return_diagrams`, алгоритм возвращает список, каждый элемент
которого содержит набор диаграмм устойчивости для соответствующего изображения исходного набора.

### Метод оценки качества классификации

Для оценки качества топологического подхода при решении задачи классификации,
пакет `classification` предоставляет метод `classify`, формирующий предсказания
и оценки их качества для девяти описанных в основной работе моделей.

Входными данными метода являются по два набора (тренировочная и тестовая выборки)
соответствующих изображений, целевых классов, извлечённых признаков и, опционально,
диаграмм устойчивости. При отсутствии диаграмм устойчивости во входных данных,
соответствующий метод (нейронная сеть с обучаемым слоем векторизации диаграмм устойчивости)
исключается из анализа.

Результат работы – pandas-таблица с метриками качества всех моделей, а также
matplotlib-изображение их матриц ошибок.

Параметры метода включают:

1) `label_names` – наименования классов для указания на изображениях матриц ошибок.

2) `confusion_matrix_include_values` – флаг, при отключении которого на изображениях
матриц ошибок не будут указываться количества каждого типа ошибок.

3) `nn_device`, `xgboost_device` и `catboost_device` обеспечивают возможность использования
графического процессора при обучении соответствующих моделей. 

4) Набор специализированных значений, позволяющих детально настраивать используемые классификаторы.

### Метод оценки качества распознавания лиц

Аналогично классификации, для оценки качества извлечённых признаков при решении задачи
распознавания лиц, пакет `face_recognition` предоставляет метод `learn`, производящий
обучение нескольких моделей и оценку их качества.

Входные данные метода – по два набора (тренировочная и тестовая выборки) соответствующих
фотографий, идентификаторов изображённых на них людей, извлечённых признаков и диаграмм устойчивости.
Следует заметить, что, в отличие от классификации, указание диаграмм устойчивости не является
опциональным при решении задачи распознавания лиц.

Результатом работы метода являются изображения диаграмм рассеяния, показывающих распределения
расстояний между латентными представлениями пар изображений одного человека и разных людей,
сформированными соответствующими моделями.

### Метод оценки качества сжатия изображений

Для анализа применимости топологических признаков при сжатии изображений, пакет `autoencoder` предоставляет
похожий на описанные ранее метод `try_autoencoders`, который производит обучение четырёх автокодировщиков
на переданном на вход наборе тренировочных данных и оценивает обученные модели на тестовом датасете.
Результатом работы метода является pandas-таблица с метриками качества предсказаний всех моделей.

### Метод оценки качества сегментации

Аналогично, пакет `segmentation` предоставляет функцию `segment`, позволяющую оценить топологические
признаки при решении задачи сегментации – поиска объектов на изображении. Входными данными метода
также являются тренировочная и тестовая выборки, но, в отличие от описанных ранее методов, в качестве
целевой переменной должны быть переданы сегментационные карты соответствующих изображений. Выходными
данными является pandas-таблица с метриками качества обученных моделей, а также контрольной модели,
в которой полностью удалена первая часть U-Net, что позволяет оценить качество фактически случайных
предсказаний в отсутствие какой-либо информации об исходном изображении.

Важно заметить, что разработанные методы сегментации, включая функцию segment,
не используют диаграммы устойчивости и не принимают их в качестве входных данных.

### Средства логирования этапов работы методов

Для наблюдения за работой библиотеки, пакет `logging` реализует механизм логирования,
позволяющий гибко настраивать количество выводимых событий, а также индикаторы прогресса
циклических методов. Для этого вместе с библиотекой поставляется интерфейс `BaseLogger`
и две его реализации: `CLILogger`, выводящий сообщения в командную строку, и `DevNullLogger`,
скрывающий все сообщения.

Для указания, какую реализацию логирования использовать при работе, пользователю необходимо
создать контекст с инициализацией соответствующего класса следующим образом:

```python
with CLILogger():
    # Код, который будет выводить сообщения в командную строку
with DevNullLogger():
    # Код, который не будет выводить сообщения
```

Такой механизм позволяет при необходимости разработать дополнительную, специализированную
реализацию логирования, соответствующую желаниям пользователя, без изменения исходного
кода библиотеки. Для этого необходимо создать новый класс, реализующий интерфейс `BaseLogger`,
и использовать его при создании контекста следующим образом:

```python
class CustomLogger(BaseLogger):
    def print(self, data):
        # Пользовательская реализация
    def pbar(self, data], total,  desc):
        # Пользовательская реализация
    def zip(self,  *iterables, desc):
        # Пользовательская реализация
    def set_pbar_postfix(self, pbar, data):
        # Пользовательская реализация

with CustomLogger():
    # Код, использующий CustomLogger для вывода сообщений
```

### Средства резервного копирования результатов

Для резервного копирования промежуточных результатов с возможностью дальнейшего их
восстановления поставляется пакет `dumping`, реализующий основанный на управлении
контекстом механизм, аналогичный средствам логирования.  Класс `BaseDumper` описывает
общий интерфейс соответствующих методов, а вместе с библиотекой поставляется две
его реализации: `NumpyDumper`, позволяющий сохранять numpy-массивы на диск, и `DevNullDumper`,
отключающий резервное копирование. Выбор реализации производится путём создания контекста с
инициализацией соответствующего класса:

```python
with NumpyDumper():
    # Код, который будет сохранять результаты на диск
with DevNullDumper():
    # Код, который не будет выполнять резервное копирование
```

Для указания имени резервной копии (для `NumpyDumper` совпадает с директорией,
куда будут сохраняться результаты) необходимо передать поддерживающему резервное копирование
методу параметр `dump_name`. Так, большинство классов библиотеки, включая `FeatureExtractor`,
принимают это значения в качестве опционального параметра в методах `fit`, `transform` и `fit_transform`.

Более того, все методы, поддерживающие резервное копирование, предоставляют возможность передачи
параметра `only_get_from_dump`, который указывает библиотеке, что все результаты были вычислены
ранее и необходимо безусловно считать их из копии, что позволяет ускорить процесс восстановления.

Наконец, использование основанного на управлении контекстом механизма позволяет при необходимости
разработать дополнительную, специализированную реализацию резервного копирования без изменения
исходного кода библиотеки. Для этого необходимо создать новый класс, реализующий интерфейс
`BaseDumper`, и использовать его при создании контекста следующим образом:

```python
class CustomDumper(BaseDumper):
    def execute(self, function, name, *function_args):
        # Пользовательская реализация
    def save_dump(self, data, name):
        # Пользовательская реализация
    def has_dump(self, name):
        # Пользовательская реализация
    def get_dump_impl_(self, name):
        # Пользовательская реализация

with CustomDumper():
    # Код, использующий CustomDumper для резервного копирования
```

### Другие элементы, предоставляемые библиотекой

Помимо описанных ранее основных методов, библиотека предоставляет и ряд вспомогательных реализаций,
краткая документация которых представлена далее. Для получения более подробных описаний методов,
включая параметры алгоритмов и типы обрабатываемых данных, следует обратиться к исходному коду библиотеки.

1) Пакет `utils`:

    1) Класс `DuplicateFeaturesRemover` реализует эффективный алгоритм удаления признаков,
    значение которых совпадает для всех изображений.

    2) Метод `image2pointcloud` преобразует набор изображений любой размерности в набор
    метрических пространств описанным в основной работе способом.

    3) Методы `rgb2gray` и `rgb2hsv` преобразуют набор цветных изображений в соответствующее
    представление: монохромное или HSV.

    4) Метод `sequence2features` реализует вычисление статистических характеристик
    числовой последовательности как описано в основной работе.
    
    5) Метод `set_random_seed` позволяет фиксировать семя случайности в недетерминированных алгоритмах.
    
    6) Метод `spread_points` формирует равномерное распределение заданного количества точек
    на отрезке некоторой длины.

2) Пакет `topology`:

    1) Класс `DiagramVectorizer` реализует предложенный в основной работе статистический
    метод векторизации диаграмм устойчивости.

    2) Классы `FiltrationExtractor` и `FiltrationsExtractor` реализуют алгоритмы извлечения
    топологических признаков из монохромных изображений путём их бинаризации с дальнейшим
    применением разнообразных фильтраций.

    3) Классы `GrayGeometryExtractor` и `GeometryExtractor` предоставляют механизм вычисления
    геометрических признаков изображений.

    4) Класс `GreyscaleExtractor` реализует простейший способ извлечения топологических признаков
    из монохромных изображений путём непосредственного построения кубических комплексов для них.

    5) Класс `PointCloudsExtractor` предоставляет возможность анализа изображений как
    метрических пространств с помощью комплексов Вьеториса – Рипса.

3) Пакет `neural_network` предоставляет утилиты для разработки нейросетевых моделей,
использованных при оценки качества решения задач классификации и распознавания лиц.

4) Пакет `classification`:

    1) Метод `estimate_quality` производит вычисление метрик качества предсказаний
    при решении задачи классификации.

    2) Класс `InformationValueFeatureSelector` реализует механизм отбора признаков
    на основе их информационной ценности для решения задачи классификации.
    
    3) Класс `NNClassifier` является общей реализацией всех нейросетевых моделей
    классификации, описанных в основной работе.

    4) Классы `BaseLearner`, `DiagramsLearner`, `NNLearner` и `SimpleTopologicalLearner`
    пакета `face_recognition` реализуют соответствующие модели распознавания лиц.

## Реализации типичных сценариев использования

### Извлечение топологических признаков

Ключевым сценарием использования библиотеки является извлечение топологических
признаков набора изображений, что может быть выполнено следующей программой:

```python
import cvtda.topology
extractor = cvtda.topology.FeatureExtractor()
train_features = extractor.fit_transform(train_images)
test_features = extractor.transform(test_images)
```
Более того, для разработки улучшенных моделей могут быть применены специализированные
методы пакета `topology`, имеющие программный интерфейс, аналогичный классу `FeatureExtractor`.

### Оценка качества классификации набора изображений

Для первичной оценки применимости топологического анализа данных к классификации набора
изображений, может быть использована следующая программа:

```python
# Считать тренировочную выборку в train_images и train_labels
# Считать тестовую выборку в переменные test_images и test_labels

import cvtda.topology
extractor = cvtda.topology.FeatureExtractor()
train_features = extractor.fit_transform(train_images)
test_features = extractor.transform(test_images)

import cvtda.classification
cvtda.classification.classify(
    train_images, train_features, train_labels, None,
    test_images, test_features, test_labels, None
)
```

### Оценка качества распознавания лиц

Для оценки качества распознавания лиц, перед вызовом функции `learn` необходимо дополнительно
восстановить из резервной копии диаграммы устойчивости следующим образом:

```python
# Считать тренировочную выборку в train_images и train_labels
# Считать тестовую выборку в переменные test_images и test_labels

import cvtda.topology
extractor = cvtda.topology.FeatureExtractor()
train_features = extractor.fit_transform(train_images, "train")
test_features = extractor.transform(test_images, "test")

extractor = cvtda.topology.FeatureExtractor(
    return_diagrams = True,
    only_get_from_dump = True
)
train_diagrams = extractor.fit_transform(train_images, "train")
test_diagrams = extractor.transform(test_images, "test")

import cvtda.face_recognition
cvtda.face_recognition.learn(
    train_images, train_features, train_labels, train_diagrams,
    test_images, test_features, test_labels, test_diagrams
)
```

## Основные сообщения об ошибках

Основные сообщения, возникающие в ходе выполнения реализованных в библиотеке алгоритмов и
действия, необходимые для их исправления, представлены в таблице А.1.

Таблица A.1 – Сообщения, возникающие при работе библиотеки
<table>
    <thead>
        <tr>
            <th>Текст сообщения</th>
            <th>Описание содержания</th>
            <th>Действия, которые необходимо предпринять</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>There is no dump at …</td>
            <td>Попытка загрузить не существующую резервную копию результатов</td>
            <td>
            
1) Убедиться, что указан верный путь до существующей резервной копии

2) Вызвать метод без флага only_get_from_dump для формирования резервной копии
            </td>
        </tr>
        <tr>
            <td>…d images are not supported</td>
            <td rowspan=2>Алгоритму переданы изображения в неподдерживаемом формате</td>
            <td rowspan=2>Убедиться, что переданные данные представляют набор монохромных или RGB изображений</td>
        </tr>
        <tr>
            <td>Images with … channels are not supported</td>
        </tr>
        <tr>
            <td>Bad image format: should be [0, 1]; received …</td>
            <td>Алгоритму переданы изображения в неподдерживаемом формате</td>
            <td>Убедиться, что значения пикселей изображений находятся в интервале [0; 1]</td>
        </tr>
        <tr>
            <td>fit() must be called before transform()</td>
            <td>Метод `transform` вызван для алгоритма, который не был перед этим настроен вызовом метода `fit`</td>
            <td>Вызвать метод `fit`</td>
        </tr>
        <tr>
            <td>The pipeline is fit for … Cannot use it with …</td>
            <td>Метод `transform` вызван с изображениями в формате, отличном от выбранного при вызове `fit`</td>
            <td>Убедиться, что форматы изображений в тренировочной и тестовой выборках совпадают</td>
        </tr>
    </tbody>
</table>
