Найти в Дзене
Когда скучно SDET`у

Подготовка датасета для обучения нейросети.

Вот никогда такого не было и вот опять. После завершения детектора думал наконец вплотную взяться за нейросеть по восстановлению фона. Но первым встал вопрос про подготовку данных для обучения. Вот какие первые ассоциации при словосочетании "обработка и подготовка изображений"? Ну, фотошоп там, лайтрум, в крайнем случае, тот же paint, если по быстрому. Для меня же обработка изображений неразрывно связана с многомерными массивами.

Но обо всем по порядку.

Собственно задача: Создать генеративно-состязательную нейросеть для восстановления фона после того как нейросеть (или отдельно пользователь) создаст маску для удаления "лишних" данных со страницы манги. Приложение (когда оно будет) удаляет данные по маске и скармливает часть страницы плюс саму маску нейросети которая и восстанавливает фон.

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

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

А тут не просто нужны страницы, а обработанные изображения. Вида было -> стало. Я отписался на форумах переводчиков манги (да и паре групп переводчиков) с просьбой поделится исходниками, но видимо не судьба.

Самому "клинить"мангу желания нет, да и долго тем более без опыта, да и фотошоп последний раз я видел лет так 10-15 назад. Заказывать на аутсорсе - дорого.

Поэтому решил проверять концепцию на синтетических данных. Тупо нарезать 300-400 (для начала) квадратов 256х256 пикселей (размер пока выбран для теста) фона, с помощью детектора собрать сотню различных масок и случайным образом создать комплект уникальных данных. Дискриминатору скормить готовые неизмененные квадраты изображений. Потом, програмным методом с квадратов удалить инфу по случайным маскам и скормить уже генератору.

Вопрос: кто будет нарезать? Я? Не думаю, долго, муторно и займет много времени. Думал обратится к аутсорсу, работа вроде как для человека работающего с этим постоянно не трудная. Но, посмотрев цены, передумал.

В конце концов, автоматизатор я или где. Пойдем более простым и менее трудоемким путем, для меня во всяком случае. Просто создал скрипт который с 1 страницы нарежет 30 случайных изображений. На написание и отладку ушло порядка часа. Скормив скрипту несколько томов манги на японском (тут не принципиально, но раз есть подготовленные данные, которые я использовал для детектора, то почему бы и нет) получил около 5000 разных изображений. Осталось отобрать из них подходящие, посмотреть на количество - если не хватит, скачать еще пару томов и так до победного.

После отбора получается как-то так
После отбора получается как-то так

Теперь работа с масками. И вот тут все стало несколько сложнее.

YOLOv8 для сигментации приводит все картинки к формату 640х840. Поэтому маскам объектов, после получения нужно возвращать натуральный размер. А после восстановления размера - они почему-то "поплыли".

В галерее видно, что маски расположенные слева "поплыли" в сторону центра. Сразу скажу, что у масок справа та же история, плывут влево, к центру. Покопавшись, понял что происходит это из-за несоответсвия соотношения сторон формата манги (130х195 мм, соотношение 1,5) к соотношению изображения YOLO (640х480, соотношение 1,33). Ну, ок, вспоминаем про нормализацию изображений на входе.

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

Решил нормализовывать изображение по алгоритму:

1) Удаляем пустые белые линии со всех сторон (кроп изображения). Результат обычно близок к соотношению 1,5

2) Дальше по формуле 1920 - высота страницы, 1440 - ширина страницы получаем количество "пустых" строк которые нужно вставить для достижения формата

3) Потом делить каждое пополам, используем целочисленное деление чтобы понять сколько нужно вставлять с каждой стороны (справа/слева, вверх/низ), к второму добавляем еще 1 если изначальное количество пикселей не кратно 2

Итог:

Итоговое изображение с нормализацией.
Итоговое изображение с нормализацией.

Ну вот и хорошо) теперь можно надергать масок, все что меньше 256х256 запихнуть в отдельные файлы, нормализовать до 256х256 (в вышеуказанный код такую функцию и заложил) и подготовить весь комплект данных.

И, блин, начать наконец-то работу с нейросетями...

Код могу, в принципе оформить в отдельную библиотеку, но пока лень. Если он хоть кому-то нужен, напишите.