Раскрашиваем чёрно-белую фотографию с помощью нейросети из 100 строк кода |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-11-15 10:51 Перевод статьи Colorizing B&W Photos with Neural Networks.
Не так давно Амир Авни с помощью нейросетей затроллил на Reddit ветку /r/Colorization, где собираются люди, увлекающиеся раскрашиванием вручную в Photoshop исторических чёрно-белых изображений. Все были изумлены качеством работы нейросети. То, на что уходит до месяца работы вручную, можно сделать за несколько секунд. Давайте воспроизведем и задокументируем процесс обработки изображений Амира. Для начала посмотрите на некоторые достижения и неудачи (в самом низу — последняя версия). Исходные чёрно-белые фотографии взяты с Unsplash. Сегодня чёрно-белые фотографии обычно раскрашивают вручную в Photoshop. Посмотрите это видео, чтобы получить представление об огромной трудоёмкости такой работы: В этой статье вы узнаете, как за три этапа построить собственную нейросеть для раскрашивания изображений. В первой части мы разберёмся с основной логикой. Построим каркас нейросети из 40 строк, это будет «альфа»-версия раскрашивающего бота. В этом коде мало таинственного, он поможет вам ознакомиться с синтаксисом. На следующем этапе мы сделаем обобщающую (generalize) нейросеть — «бета»-версию. Она уже сможет раскрашивать изображения, которые ей не знакомы. В «окончательной» версии мы объединим нашу нейросеть с классификатором. Для этого возьмём Inception Resnet V2, обученный на 1,2 млн изображений. А нейросеть обучим раскрашиванию на изображениях с Unsplash. Если не терпится, то вот Jupyter Notebook с альфа-версией бота. Также можете посмотреть три версии на FloydHub и GitHub, и ещё код, использованный во всех экспериментах, которые проводились на облачных видеокартах сервиса FloydHub. Основная логика В этом разделе мы рассмотрим рендеринг изображения, поговорим о теории цифрового цвета и основной логике нейросети. Чёрно-белые изображения можно представить в виде сетки из пикселей. У каждого пикселя есть значение яркости, лежащее в диапазоне от 0 до 255, от чёрного до белого.Как и в чёрно-белом изображении, пиксели каждого слоя цветного изображения содержат значение от 0 до 255. Ноль означает, что у этого пикселя в данном слое нет цвета. Если во всех трёх каналах стоят нули, то в результате на картинке получается чёрный пиксель. Как вы знаете, нейросеть устанавливает взаимосвязь между входным и выходным значениями. В нашем случае нейросеть должна найти связующие черты между чёрно-белыми и цветными изображениями. То есть мы ищем свойства, по которым можно сопоставить значения из чёрно-белой сетки со значениями из трёх цветных. f() — нейросеть, [B&W] — входные данные, [R],[G],[B] — выходные данные. Альфа-версия Сначала сделаем простую версию нейросети, которая будет раскрашивать женское лицо. По мере добавления новых возможностей вы будете знакомиться с основным синтаксисом нашей модели. За 40 строк кода мы перейдём от левой картинки — чёрно-белой — к средней, которая сделана нашей нейросетью. Правая картинка — это оригинальная фотография, из которой мы сделали чёрно-белую. Нейросеть обучалась и тестировалась на одном изображении, об этом мы поговорим в разделе, посвящённом бета-версии.Цветовое пространство Сначала воспользуемся алгоритмом изменения цветовых каналов с RGB на Lab. L означает светлота (lightness), a и b — декартовы координаты, определяющие положение цвета в диапазоне, соответственно, от зелёного до красного и от синего до жёлтого.Как видите, изображение в пространстве Lab содержит один слой градаций серого, а три цветных слоя упакованы в два. Поэтому мы можем использовать в окончательном изображении исходный чёрно-белый вариант. Осталось вычислить ещё два канала. Научный факт: 94% рецепторов сетчатки нашего глаза отвечают за определение яркости. И только 6% рецепторов распознают цвета. Поэтому для вас чёрно-белое изображение выглядит гораздо отчётливее цветных слоёв. Это ещё одна причина, по которой мы будем использовать эту картинку в окончательном варианте. Из градаций серого в цвет В качестве входных данных возьмём слой с градациями серого, и на его основе сгенерируем цветные слои a и b в цветовом пространстве Lab. Его же мы возьмём и в качестве L-слоя окончательной картинки. Для получения двух слоёв из одного слоя, воспользуемся свёрточными фильтрами. Их можно представить как синее и красное стекло в 3D-очках. Фильтры определяют, что мы увидим на картинке. Они могут подчёркивать или скрывать какую-то часть изображения, чтобы наш глаз извлек нужную информацию. Нейросеть тоже может с помощью фильтра создать новое изображение или свести несколько фильтров в одну картинку.В свёрточных нейросетях каждый фильтр автоматически подстраивается, чтобы легче было получить нужные выходные данные. Мы наложим сотни фильтров, а затем сведём их воедино и получим слои a и b. Прежде чем переходить к подробностям работы кода, давайте его запустим. Развёртывание кода на FloydHub Если вы раньше не работали с FloydHub, то можете запустить пока инсталляцию и посмотреть пятиминутное видеоруководство или пошаговые инструкции. FloydHub — лучший и простейший способ глубокого обучения моделей на облачных видеокартах.Альфа-версия После установки FloydHub введите команду:git clone https://github.com/emilwallner/Coloring-greyscale-images-in-Keras Затем откройте папку и инициализируйте FloydHub. cd Coloring-greyscale-images-in-Keras/floydhub В вашем браузере откроется веб-панель FloydHub. Вам предложат создать новый FloydHub-проект под названием colornet. Когда вы его создадите, возвращайтесь в терминал и выполните ту же команду инициализации. floyd init colornet Запускаем задачу: floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard Несколько пояснений:
Если вы можете подключить видеокарты к выполнению задачи, то добавьте в команду флаг –gpu . Получится примерно в 50 раз быстрее.Перейдите в Jupyter Notebook. На сайте FloydHub во вкладке Jobs кликните на ссылку Jupyter Notebook и найдите файл: floydhub/Alpha version/working_floyd_pink_light_full.ipynb Откройте файл и на всех ячейках нажмите Shift+Enter. Постепенно увеличивайте значение периодов (epoch value), чтобы понять, как учится нейросеть. model.fit(x=X, y=Y, batch_size=1, epochs=1) Начните с epochs=1, затем увеличивайте до 10, 100, 500, 1000 и 3000. Это значение показывает, сколько раз нейросеть обучается на изображении. Как только вы обучите нейросеть, то найдёте файл img_result.png в главной папке. # Get images FloydHub-команда для запуска этой сети: floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard Технические пояснения Напомним, что на входе у нас сетка, представляющая чёрно-белое изображение. А на выходе — две сетки со значениями цветов. Между входными и выходными значениями мы создали связующие фильтры. У нас получилась свёрточная нейросеть. Для обучения сети используются цветные изображения. Мы преобразовали из цветового пространства RGB в Lab. Чёрно-белый слой подаётся на вход, а на выходе получаются два раскрашенных слоя.Реальные значения цветов меняются от —128 до 128. В пространстве Lab это диапазон по умолчанию. Если каждое значение разделить на 128, то все они окажутся в границах от —1 до 1. Такая «нормализация» позволяет сравнивать погрешность нашего вычисления. После вычисления результирующей погрешности нейросеть обновляет фильтры, чтобы скорректировать результат следующей итерации. Вся процедура повторяется циклически, пока погрешность не станет минимальной. Давайте разберёмся с синтаксисом этого кода: X = rgb2lab(1.0/255*image)[:,:,0] 1.0/255 означает, что мы используем 24-битное цветовое пространство RGB. То есть для каждого цветового канала мы используем значения в диапазоне от 0 до 255. Это даёт нам 16,7 миллиона цветов. Но поскольку человеческий глаз может распознавать лишь от 2 до 10 млн цветов, то использовать более широкое цветовое пространство не имеет смысла. Y = Y / 128 Цветовое пространство Lab использует другой диапазон. Цветовой спектр ab варьируется от —128 до 128. Если поделить все значения выходного слоя на 128, то они уложатся в дипазон от —1 до 1, и тогда можно будет сопоставить эти значения с теми, что вычислила наша нейросеть. После того, как с помощью функции rgb2lab() преобразовали цветовое пространство, мы с помощью [:,:, 0] выбираем чёрно-белый слой. Это входные данные для нейросети. [:,:, 1: ] выбирает два цветных слоя, красно-зелёный и сине-жёлтый.После обучения нейросети выполняем последнее вычисление, которое преобразуем в картинку. output = model.predict(X) Здесь мы подаём на вход чёрно-белое изображение и прогоняем его через обученную нейросеть. Берём все выходные значения от —1 до 1 и умножаем их на 128. Так мы получаем корректные цвета в системе Lab. canvas = np.zeros((400, 400, 3)) Создаём чёрный RGB-холст, заполнив все три слоя нулями. Затем копируем чёрно-белый слой из тестового изображения и добавляем два цветных слоя. Получившийся массив значений пикселей преобразуем в изображение. Чему мы научились при работе над альфа-версией
Бета-версия Предложите альфа-версии раскрасить изображение, на котором она не обучалась, и сразу поймёте, в чём главный недостаток этой версии. Она не справится. Дело в том, что нейросеть запомнила информацию. Она не научилась раскрашивать незнакомое изображение. И мы это исправим в бета-версии — научим нейросеть обобщать. Ниже показано, как бета-версия раскрасила проверочные картинки.Вместо использования Imagenet мы создали на FloydHub публичный датасет с более качественными изображениями. Они взяты с Unsplash?—?сайта, где выкладываются снимки профессиональных фотографов. В датасете 9500 обучающих изображений и 500 проверочных. Выделитель признаков Наша нейросеть ищет характеристики, связывающие чёрно-белые изображения с их цветными версиями. Представьте, что вам нужно раскрасить чёрно-белые картинки, но вы можете видеть на экране только девять пикселей одновременно. Вы можете просматривать каждую картинку слева направо и сверху вниз, стараясь вычислить цвет каждого пикселя.Пусть эти девять пикселей находятся с краю ноздри женщины. Как вы понимаете, правильно выбрать цвет здесь почти невозможно, так что придётся разбивать решение задачи на этапы. Во-первых, ищем простые характерные структуры: диагональные линии, только чёрные пиксели и так далее. В каждом квадратике из 9 пикселей мы ищем одну и ту же структуру и удаляем всё, что ей не соответствует. В результате мы создали 64 новых изображения из 64 наших минифильтров. Количество обработанных фильтрами изображений на каждом этапе. Если снова просмотрим изображения, то обнаружим те же маленькие повторяющиеся структуры, которые мы уже определили. Чтобы лучше проанализировать изображение, уменьшим его размер вдвое. Уменьшаем размер в три этапа. У нас ещё остался фильтр 3х3, которым нужно просканировать каждое изображение. Но если мы применим наши более простые фильтры к новым квадратам из девяти пикселей, то можно обнаружить более сложные структуры. Например, полукруг, маленькая точка или линия. Мы снова раз за разом находим на картинке одну и ту же повторяющуюся структуру. На этот раз генерируем 128 новых обработанных фильтрами изображений. Через пару этапов обработанные фильтрами изображения станут выглядеть так: Повторимся: вы начинаете с поиска простых свойств, например, краёв. По мере обработки слои объединяются в структуры, затем в более сложные черты, и в конце концов получается лицо. Подробнее объясняется в этом видео: От извлечения свойств к цвету Нейросеть действует по принципу проб и ошибок. Сначала она случайным образом назначает цвет каждому пикселю. Затем по каждому пикселю вычисляет ошибки и корректирует фильтры, чтобы в следующей попытке улучшить результаты. Нейросеть подстраивает свои фильтры, отталкиваясь от результатов с самыми большими значениями ошибок. В нашем случае нейросеть решает, нужно ли раскрашивать или нет, и как расположить на картинке разные объекты. Сначала она красит все объекты в коричневый. Этот цвет больше всего похож на все остальные цвета, поэтому с ним при его использовании получаются самые маленькие ошибки.Из-за однообразия обучающих данных нейросеть старается понять различия между теми или иными объектами. Она пока не может вычислить более точные цветовые оттенки, этим мы займёмся при создании полной версии нейросети. Вот код бета-версии: # Get images FloydHub-команда для запуска бета-версии нейросети: floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard Технические пояснения От других нейросетей, работающих с изображениями, наша отличается тем, что для неё важно расположение пикселей. У раскрашивающих нейросетей размер изображения или соотношение сторон остаётся неизменным. А у сетей других типов изображение искажается по мере приближения к окончательной версии. Слой пулинга с функцией максимума, применяемый в классифицирующих сетях, увеличивает плотность информации, но при этом искажает картинку. Он оценивает только информацию, а не макет изображения. А в раскрашивающих сетях для уменьшения ширины и высоты вдвое мы используем шаг 2 (stride of 2). Плотность информации тоже увеличивается, но картинка не искажается.Также наша нейросеть отличается от прочих слоями повышения дискретизации (upsampling) и сохранением соотношения сторон изображения. Классифицирующие сети заботятся только об итоговой классификации, поэтому постепенно уменьшают размер и качество картинки по мере её прогона через нейросеть. Раскрашивающие нейросети не меняют соотношение сторон изображения. Для этого с помощью параметра *padding='same'* добавляются белые поля, как на иллюстрации выше. В противном случае каждый свёрточный слой обрезал бы изображения.Чтобы удвоить размер картинки, раскрашивающая нейросеть использует слой повышения дискретизации. for filename in os.listdir('/Color_300/Train/'): Этот цикл for-loop сначала подсчитывает имена всех файлов в директории, проходит по директории и преобразует все картинки в массивы пикселей, и наконец объединяет их в огромный вектор.datagen = ImageDataGenerator( С помощью ImageDataGenerator можно включить генератор изображений. Тогда каждое изображение будет отличаться от предыдущих, что ускорит обучение нейросети. Настройка shear_range задаёт наклон изображения влево или вправо, также его можно увеличить, повернуть или отразить по горизонтали.batch_size = 50 Применим эти настройки к картинкам в папке Xtrain и сгенерируем новые изображения. Затем извлечём чёрно-белый слой для X_batch и два цвета для двух цветных слоёв.model.fit_generator(image_a_b_gen(batch_size), steps_per_epoch=1, epochs=1000) Чем мощнее ваша видеокарта, тем больше картинок вы сможете в ней обрабатывать одновременно. Например, описанная система умеет обрабатывать 50-100 изображений. Значение параметра steps_per_epoch получено делением количества обучающих изображений на размер серии (batch size). Например: если у нас 100 картинок, а размер серии равен 50, то получим 2 этапа в период. Количество периодов определяет, сколько раз вы будете обучать нейросеть на всех картинках. Если у вас 10 тыс. картинок и 21 период, то это займёт около 11 часов на видеокарте Tesla K80. Чему научились
Полная версия нейросети Наша окончательная версия раскрашивающей нейросети содержит четыре компонента. Предыдущую сеть мы разбили на кодировщик и декодировщик, а между ними слой слияния (fusion layer). Если вы не знакомы с классифицирующими нейросетями, то рекомендуем почитать это руководство: http://cs231n.github.io/classification/.Входные данные одновременно проходят через кодировщик и через самый мощный современный классификатор —? Inception ResNet v2. Это нейросеть, обученная на 1,2 млн изображений. Мы извлекаем слой классификации и объединяем его с выходными данными кодировщика. Более подробное визуальное пояснение: https://github.com/baldassarreFe/deep-koalarization. Если перенести обучение из классификатора в раскрашивающую сеть, то она сможет понять, что изображено на картинке, а значит и сопоставлять представление объекта со схемой раскрашивания. Вот некоторые проверочные изображения, для обучения сети использовалось только 20 картинок. Самые распространённые архитектуры из различных исследовательских работ:
Цветовые пространства: Lab, YUV, HSV и LUV (подробнее здесь и здесь) Потери: средняя квадратическая ошибка, классификация, взвешенная классификация (ссылка). Мы выбрали архитектуру со «слоем слияния» (пятая в списке), потому что она давала лучшие результаты. Также в ней проще разобраться и легче её воспроизвести в Keras. Хотя это не самая сильная архитектура, но для начала сгодится. Структура нашей нейросети позаимствована из работы Федерико Бальдасарре и его коллег, и адаптирована для работы с Keras. Примечание: в этом коде вместо последовательной модели Keras используется функциональный API. [Документация] # Get images FloydHub-команда для запуска полной версии нейросети: floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard Технические пояснения Функциональный API Keras замечательно подходит для конкатенации или объединения нескольких моделей.Для начала скачаем нейросеть Inception ResNet v2 и загрузим значения весов. Раз мы параллельно будем использовать две модели, то нужно определить, какие именно. Это делается в Tensorflow, бэкенде Keras. inception = InceptionResNetV2(weights=None, include_top=True) Создадим серию (batch) из подправленных изображений. Переведём их в ч/б и прогоним через модель Inception ResNet. grayscaled_rgb = gray2rgb(rgb2gray(batch)) Сначала нужно изменить размер картинок, чтобы скормить их модели. Затем с помощью препроцессора приведём пиксели и значения цветом к нужному формату. И наконец прогоним изображения через сеть Inception и извлечём итоговой слой модели. def create_inception_embedding(grayscaled_rgb): Вернёмся к генератору. Для каждой серии сгенерируем по 20 изображений описанного ниже формата. На Tesla K80 GPU ушло около часа. При использовании такой модели эта видеокарта может генерировать до 50 изображений за раз без каких-либо проблем с памятью. yield ([X_batch, create_inception_embedding(grayscaled_rgb)], Y_batch) Это соответствует формату нашей модели colornet. model = Model(inputs=[encoder_input, embed_input], outputs=decoder_output) encoder_inputis передан в модель Encoder, её выходные данные потом объединяются в слое слияния с embed_inputin ; выходные данные слияния подаются на вход модели Decoder, которая возвращает итоговые данные — decoder_output .fusion_output = RepeatVector(32 * 32)(embed_input) В слое слияния мы сначала слой с 1000 категорий (1000 category layer) умножаем на 1024 (32 * 32). Так мы получаем из модели Inception 1024 ряда итогового слоя. Сетка 32 х 32 переводится из двухмерного в трёхмерное представление, с 1000 столбцов категорий (category pillars). Затем столбцы связываются с выходными данными модели кодировщика. Применяем свёрточную сеть с 254 фильтрами и ядром 1х1 к окончательным результатам слоя слияния. Чему научились
Что дальше Раскрашивание изображений — это очень интересная задача. Здесь приходится заниматься и наукой, и творчеством. Возможно, эта статья поможет вам сэкономить время. С чего вы могли бы начать:
Можете раскрасить свои чёрно-белые изображения с помощью всех трёх описанных версий нейросети на FloydHub.
Источник: habrahabr.ru Комментарии: |
|