# Разметка кластеров знаков попарным сравнением двух детекций

## Начальная разметка
Чтобы ускорить и удешевить процесс разметки данные скрипты используют предварительную разметку кластеров.
Данную разметку можно получить с помощью уже реализованных алгоритмов, чтобы затем использовать Толоку только для исправлений полученных ошибок.
Начальная разметка должна включать в себя:
1) YT таблицу с параметрами feature'ей
2) JSON файл с детекциями
3) JSON файл с предварительными кластерами

## Первый этап разметки
На первом этапе разметки производится проверка связей внутри кластеров.
Для этого в толоку загружаются задания, в которых каждый элемент кластера сравнивается с одним выбранным "главным" элементом в кластере.
Таким образом на данном этапе создается N - 1 задание для каждого кластера, где N - количество элементов в кластере.
Для генерации таких заданий используется generate_intracluster_tasks.py.
Пример использования:
python3 generate_intracluster_tasks.py \
    --feature-table //home/features \
    --detections objects.json \
    --clusters clusters.json \
    --tasks tasks.json

Параметры:
1) feature-table - таблица с параметрами feature'ей на YT
2) detections - файл с детекциями в том же формате, что и файлы, используемые в датасетах карты знаков
3) clusters - файл с кластерами в том же формате, что и файлы, используемые в датасетах карты знаков
4) tasks - итоговый файл с заданиями для Толоки.

Получаемый файл с заданиями проще все залить в Толоку с помощью специальных кубиков в Нирване.
Пример графа с подобными заданиями:
https://nirvana.yandex-team.ru/flow/9cc077bb-53c8-4c75-b373-787475dbb3d0/e1a7561d-6787-4b28-9657-64400a3a203f/graph

Данный граф загружает задания в Толоку (sandbox или production) и дожидается выполнения всех заданий.
После того как граф успешно завершится, мы получим файл с ответами от толокеров.

Далее необходимо применить ответы толокеров к исходным кластерам.
Сделать это можно с помощью apply_intracluster_assignments.py
Пример использования:
python3 apply_intracluster_assignments.py \
    --clusters clusters.json \
    --assignments assignments.json \
    --new_clusters new_clusters.json

Параметры:
1) clusters - файл с исходными кластерами, которые переразмечали толокеров
2) assignments - ответы толокеров для пар из кластеров clusters
3) new_clusters - новый набор кластеров, получаемый после применения ответов толокеров

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

С полученными кластерами повторяем те же самые операции, что и с исходным набором кластеров:
1) Генерируем задания
2) Загружаем в Толоку через Нирвану
3) Получаем ответы от толокеров
4) Применяем полученные ответы, получаем новый набор кластеров

Повторяем эти действия до тех пор, пока набор новых кластеров не станет пустым.
После того как удается достичь такого шага, необходимо взять все файлы с ответами толокеров и исходный набор кластеров и применить к ним весь набор ответов.
В результате получится итоговый набор кластеров на этом этапе.
Пример использования:
python3 apply_intracluster_assignments_list.py \
    --clusters clusters.json \
    --assignments assignments \
    --new_clusters new_clusters.json

Параметры:
1) clusters - исходный набор кластеров
2) assignments - папка со всеми файлами с ответами толокеров
3) new_clusters - итоговый набор кластеров после первого этапа

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

## Второй этап разметки
На втором этапе разметки необходимо склеить кластера, полученные на первом этапе. В наборе кластеров, который мы получили после первого этапа, разные детекции одного и того же знака могут находиться в разных кластерах.
Поэтому надо проверить все возможные пары кластеров, и если они содержат детекции одного и того же объекта, то их нужно склеить в один.
Для этого применяется файл generate_extracluster_tasks.py.
Пример использования:
python3 generate_extracluster_tasks.py \
    --feature-table //home/features \
    --detections objects.json \
    --clusters clusters.json \
    --distance 100 \
    --heading-diff 90 \
    --tasks tasks.json

Параметры:
1) feature-table - YT таблица с параметрами feature'ей
2) detections - JSON файл с детекциями
3) clusters - JSON файл с кластерами
4) distance - максимальное расстояние между главными детекциями кластеров, которые будут проверяться
5) heading-diff - максимальная разница между направлениями feature'ы у главных детекций кластеров, которые будут проверяться
6) tasks - файл с заданиями для Толоки

Полученный файл загружается в Толоку с помощью того же графа, что был указан ранее.
После того как все задания будут выполнены, мы получим файл с ответами толокеров
Ответы толокеров надо применить к набору кластеров через apply_extracluster_assignments.py
Пример использования:
python3 apply_extracluster_assignments.py \
    --clusters clusters.json \
    --assignments assignments.json \
    --new_clusters new_clusters.json

В итоге мы получим файл new_clusters.json, который содержит итоговую разметку кластеров.
