Как мы разработали уникальный алгоритм удаления эффекта красных глаз для Epson

12 комментариев
Как мы разработали уникальный алгоритм удаления эффекта красных глаз для Epson

В сентябре стартовали продажи самого быстрого сканера фотографий на рынке Epson FastFoto FF-640. Цель производителя достаточно амбициозна: ввести в жизнь рядовых пользователей высокоскоростной сканер, который бы позволял оцифровывать бумажные фотографии в домашних условиях, параллельно улучшая их качество. Над инновационным продуктом трудилась международная команда, в том числе минская группа разработчиков Softeq Development. Работа над десктопным приложением под Windows и macOS, которое предоставляется в комплекте поставки сканера, продолжалась почти год.

О внедрении уникальной функции автоматического удаления эффекта красных глаз читателям dev.by рассказывает Артём Мерц, Unit Lead в Softeq Development.

Читать далее

Вообще тема обработки изображений очень интересная и широкая, а для меня она была практически новой. У нас когда-то был курс в университете, но этого было, конечно, недостаточно, чтобы имплементировать все, что требовалось на проекте. Поэтому сначала я решил подтянуть матчасть. Прочитал книгу Digital Image Processing автора Rafael C. Gonzalez, прошел курс Fundamentals of Digital Image and Video Processing на Coursera, перелопатил кучу документации и блогов. Это позволило добиться хорошего результата на практике, но давайте обо всем по порядку.

Итак, мы разработали три алгоритма обработки фото. 

Алгоритм восстановления цвета

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

Алгоритм улучшения фото

Этот алгоритм призван добавлять контрастности и вытягивать цвета фотографии. Эффект можно отдаленно сравнить с ретушью в фотошопе.

Конечно, такие решения не могут быть универсальными на 100%. Если в большинстве случаев алгоритмы по выравниванию баланса белого или увеличению контраста отрабатывают на «ура», то в определенных сценах они портят изображения: фото заката, например, после автоматической обработки стало голубым. При этом с точки зрения частотных метрик фото идеально, однако, человеческий глаз (и мозг) воспринимает все по-другому. 

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

Тем не менее в большинстве случаев оба эти алгоритма действительно улучшали фотографии. На случай исключений, как в примере с закатом, в приложении предусмотрена возможность откатить автоматическую коррекцию и оставить просто «голый» скан. 

Алгоритм автоматического удаления эффекта красных глаз

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

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

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

определение лица — определение глаз — определение зрачка — ретушь зрачка.

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

На этом этапе мы использовали библиотеку OpenCV, но у её алгоритма по поиску образов есть ограничения. Например, если голова человека на фото наклонена или повернута, то лицо не определяется. OpenCV определяет и исключает глаза котов, собак, игрушек, что облегчило нам задачу. Например, на одной из тестовых фото человек обнимал ростовую куклу Гуфи. Так вот у Гуфи, по мнению OpenCV, глаз нет. Уже неплохо!

Однако, над настройкой самого алгоритма обнаружения глаз на лице от OpenCV нам пришлось поколдовать. Изначально он подразумевает, что программист может указать параметры точности для нахождения заданного образа. Проблема в том, что если указать эти параметры слишком точными, то найдутся только самые «явные» глаза, а многие менее очевидные не будут обнаружены. Наоборот, если понизить эти параметры, то глаза найдутся и у Гуффи.

В основе нашей модели лежало то, что у лица по определению два глаза, один из которых слева, а другой — справа. Звучит смешно и очевидно, но на практике, когда мы уменьшали точность, то глаз могло найтись пять, а при увеличении — могло не оказаться вообще. Мы пытались найти баланс между этими числами, поэтому приходилось вводить дополнительные критерии. Например: мы разбивали распознанное лицо по вертикали пополам и уже на каждой из половинок искали по 1 глазу. Если их оказывалось несколько, скажем, пять, мы начинали сравнивать положение и размер прямоугольников — «кандидатов в глаза». Если группа потенциальных глаз из четырех прямоугольников была сконцентрирована в одном месте, а ещё один висел где-то на отшибе, то мы делали предположение, что наверно это мусор, а вот в той группе прячется искомый глаз.

К сожалению (или к счастью), в рамках проекта нам не довелось заняться обучением нейронных сетей, которые лежат в основе технологии распознавания объектов на изображениях, хотя такой опыт у нас в команде есть. Мы использовали готовые каскады: смотрели какие из них лучше подходят для нашего кейса, какие статистически дают меньше ошибок — и выбирали наиболее эффективные.

Нюансы со зрачками: RGB vs HSL и эквализация гистограмм

Переходим к этапу определения и закрашивания зрачка. Изначально мы пытались использовать стандартные методы. Мы знали, где глаз, и, казалось бы, оставалось лишь найти круглое пятно около его центра. Но реальность такова, что на старых фотках зрачки оказывались квадратными, ромбовидными — любой формы, но только не круглые. Это привело нас к решению ввести параметр цвета.

Однако, и с цветом оказалось все не так просто. Сначала мы пошли по модели, основанной на RGB-цветах. Мы сравнивали канал красного (R) c каналами зеленого и синего (G и B), и если он был больше них на определённую величину, то мы утверждали, что красный цвет найден. Но на сканах фоток зрачки были всех оттенков (от розового до оранжевого), при обработке всё размыливалось, и результат вообще не коррелировал с оригиналом.

Так мы пришли к модели HSL (и HSV). В ней один из каналов отвечает за оттенок, что позволило нам выделять сектор красного, одновременно анализируя его яркость и насыщенность. При этом мы учитывали эти три показателя для всей картинки, а не только для области зрачка, чтобы получить усредненное значение. Благодаря этому мы статистически поняли, на сколько красный зрачок по яркости и насыщенности отличается от всего остального.

Итак весь процесс выглядел следующим образом: 

Мы вырезали глаз и анализировали цвета на картинке: чем дальше каждый пиксель от того идеального красного, который мы ищем, тем он темнее, и чем ближе — тем белее. В результате мы получаем картинку распределения нужного красного на глазу. Следующим этапом мы применяли подход под названием эквализация гистограмм. Упрощённое объяснение ниже, а более подробно можно почитать здесь и здесь

По оси Х расположены все возможные цвета, пронумерованные от 0 (максимально чёрный) до 255 (максимально белый), а ось Y — это количество каждого из цветов. Чем более спокойный, плоский график, тем более разноцветное и контрастное изображение. И наоборот: пик означает превалирование какого-то одного цвета и ближайших к нему оттенков. Так вот эквализация гистограмм позволила нам найти такой пик (в нашем случае красный), увеличивая контрастность.

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

Наглядное представление этапов thresholding

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

Национальный вопрос

Довольно весело проходил тюнинг алгоритма для обработки фотографий людей разных рас. В тестовых целях мы использовали несколько фотографий темнокожих людей и индейцев. Оттенок их кожи сам по себе достаточно красный, что затрудняло определение красного зрачка. Статистический анализ всего изображения очень помогал в таких случаях. Мы брали средний показатель красного по фото и поднимали минимальный уровень, чтобы в итоге на основании данных об освещенности и насыщенности найти зрачок. Изначально наш алгоритм был «расистом» и таких гибких допущений не делал.

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

Мы гордимся полученным результатом. Аналогов у нашего алгоритма нет. Он автоматизирует полный цикл: от нахождения лица до собственно редактирования красных зрачков, без вовлечения пользователя. Точность распознавания и закрашивания красных глаз около 70% при 300 dpi. Это очень хороший результат. С увеличением разрешение фото до 600 dpi точность также возрастает. Сам Epson остался очень доволен работой минской команды Softeq, и наше сотрудничество расширяется по многим направлениям.

Стек технологий десктопного приложения:

  • В основе лежит .NET для Windows и Mono/Xamarin.Mac для Mac.
  • Для нативного UI мы используем WPF и Cocoa/Interface Builder.
  • Функционал по обработке изображений написан на C++ при поддержке фреймворков OpenCV и ImageMagick.
  • Общение со сканером происходит через TWAIN-фреймворк, используя кастомный протокол.
  • Инсталлятор на Windows сделан с помощью Wix Toolset.
  • Приложение интегрируется с Facebook и Google Drive по REST API.
  • Написаны различные скрипты на Python, AppleScript, Shell для постановки цифровой подписи, автоматизации сборки компонентов и др.

Хотите сообщить важную новость?

Пишите в наш Телеграм

Читайте также

Мобильные геймеры протестировали сеть 5G от A1
Мобильные геймеры протестировали сеть 5G от A1

Мобильные геймеры протестировали сеть 5G от A1

1 комментарий
В Беларуси почти 47 тысяч случаев заболевания коронавирусом
В Беларуси почти 47 тысяч случаев заболевания коронавирусом

В Беларуси почти 47 тысяч случаев заболевания коронавирусом

EPAM запустил систему платформ для удалённых сотрудников. Можно попасть в штат
EPAM запустил систему платформ для удалённых сотрудников. Можно попасть в штат

EPAM запустил систему платформ для удалённых сотрудников. Можно попасть в штат

4 комментария
Минздрав подтвердил почти 46 тысяч случаев коронавируса
Минздрав подтвердил почти 46 тысяч случаев коронавируса

Минздрав подтвердил почти 46 тысяч случаев коронавируса

Обсуждение

Артем Воробьев
Артем Воробьев Technical Process Architect в Softeq Development
8

Ребята, молодцы! Горжусь вами :)

12

А каскады для лиц и глаз какие использовали - стандартные из OpenCV или сами чего обучали?

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

Anonymous
Anonymous Marketing & PR Director в Softeq Development
7

Игорь, спасибо большое! Мы очень старались сделать интересный материал!

Anonymous
Anonymous Unity Lead Developer в Softeq Development
5

Игорь, спасибо большое за вопрос!
Мы использовали стандартные из OpenCV:
haarcascade_frontalface_alt.xml - для лиц
haarcascade_eye_tree_eyeglasses.xml - для глаз
К тому же, выбирая каскады, стоит принимать во внимание тот факт, что в стандартном пакете Open CV есть каскады как использующие технологию Cuda, так и их аналоги но не использующие. Предпочтение стоит отдавать первым, если не хотите получить проблемы на разных девайсах.

2

Ну мы для обнаружения лиц тот же каскад используем. Он вроде как из стандартных наилучшую точность показывает. Хотя у нас своя специфика - при обработке видео быстродействие иногда более приоритетно, чем наивысшая точность. Но у нас для этого собственная оптимизированная реализация HAAR и LBP классификаторов.

Anonymous
Anonymous
-3

Фотошоп умел делать тоже самое еще в прошлом тысячелетии.

Anonymous
Anonymous Unity Lead Developer в Softeq Development
4

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

3

В целом то, что решённая задача относится к разряду R&D - уже радует, а то, что она дошла до "продакшена" на такой большой серии как практикует Epson - радует в двойне. Несмотря на чистую эмпирику на выходе - насколько видно из статьи результат заказчика более чем удовлетворяет. Хотя для проформы можно "старчески поскрипеть" про какие-нибудь фильтры Габора, которые так же неплохо детектируют различные характерные локальные области, но это так... не меняет сути. Ещё пару-тройку итераций и доведёте до стадии "конфетки". Вопрос только - какая мощность вашей тестовой выборки была на финальной стадии тестирования алгоритма?

Anonymous
Anonymous Unity Lead Developer в Softeq Development
0

Спасибо за вопрос. Финальная выборка состояла из 100+ фото с людьми и лицами, плюс фото без лиц. В целом, что в принципе и логично, после автоматизации процесса тестирования качества алгоритма (мы просто написали скрипт, который прогонял нашу программу по поиску лиц, глаз и зрачков и сравнивал с реальными значениями установленными вручную) эти проверку удалось значительно ускорить.

3

Молодцы!
Тоже (как и Дмитрия, в сообщении выше) интересует вопрос о мощности тестовой выборки. Кстати, а результат достигался и проверялся на одном и том же наборе снимков? Или для этапа приемочного тестирования, epson подготовил выборку, ранее не доступную разработчикам?

Правильно ли я понял, что под точностью в 70% имеется ввиду sensitivity (aka TPR, aka recall) равный 0.7 (т.е., например, если из 300 фото красные глаза были на 100, то алгоритм найдет (и исправит) из них 70). А можете рассказать какой был false positive rate (aka fall-out) т.е. в примере выше, на 200х фотографиях без красных глаз, как часто алгоритм ошибочно находил и "исправлял" красные глаза? И какие именно объекты обычно ошибочно воспринимались как красные глаза (если, конечно, FPR у вас не нулевой, что было бы довольно крутым достижением даже для TPR в 70%).

Если сможете привести confusion matrix, это ответит сразу на все вопросы выше :-)

P.S. Побольше бы именно таких статей на dev.by
P.P.S. "Мы вырезали глаз и анализировали цвета..." хорошо, что я это на форуме программистов читаю, а не медиков :-)

0

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

1

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

Спасибо! 

Получать рассылки dev.by про белорусское ИТ

Что-то пошло не так. Попробуйте позже