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

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

Ознакомьтесь с моей другой статьей на Medium, в которой подробно рассматривается функция распознавания лиц.

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

Для этого нам нужно определить контрольные точки лица.

Ориентиры - это заранее определенные и пронумерованные места на грани:

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

Точно так же, если я хочу отслеживать брови, я бы отслеживал точки 17–21 и 22–26, которые отслеживают левую и правую брови.

Теперь можно определять эмоции или отслеживать позу головы, отслеживая ориентиры и анализируя, как они меняются с течением времени.

Я собираюсь создать приложение, которое может обнаруживать все ориентиры на всех лицах, видимых на изображении. Я буду использовать C #, Dlib, DlibDotNet и NET Core v3 и постараюсь достичь своей цели с минимумом кода.

Dlib - это библиотека для обнаружения лиц. Он предназначен для проектов C и C ++, но Takuya Takeuchi создал пакет NuGet под названием DlibDotNet, который предоставляет полный API Dlib для C #.

А NET Core - это многоплатформенная платформа Microsoft NET Framework, работающая в Windows, OS / X и Linux. Это будущее кроссплатформенной разработки NET.

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

Я буду использовать следующее изображение для тестирования своего приложения:

Это знаменитое селфи, которое Эллен ДеДженерес сделала на церемонии вручения Оскара в 2014 году. Это отличный тестовый снимок, потому что все смотрят в камеру, а у нас есть пара знаменитостей, чьи лица видны лишь частично.

Сохраните это изображение как «input.jpg».

Давайте начнем. Вот как настроить новый консольный проект в NET Core:

$ dotnet new console -o DetectLandmarks
$ cd DetectLandmarks

Затем мне нужно установить нужные пакеты ML.NET:

$ dotnet add package DlibDotNet

Это было просто! Этот единственный пакет NuGet устанавливает Dlib и оболочку DlibDotNet и настраивает все для вашей операционной системы.

Если вы работаете на Mac, как я, вам придется выполнить один дополнительный шаг. DlibDotNet требует библиотеки XQuartz, но она не устанавливается по умолчанию в чистой системе OS / X.

Вы можете легко установить XQuartz с помощью homebrew:

$ brew cask install xquartz

Вот и все.

Теперь я готов добавить код. Вот как должен выглядеть Program.cs:

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

А ShapePredictor.Deserialize загружает файл конфигурации из 68 точек для встроенного детектора ориентиров Dlib и инициализирует его. Вы можете скачать этот файл здесь.

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

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

Метод Dlib.LoadImage ‹RgbPixel› загружает изображение в память с чередованием цветовых каналов. Затем метод Оператор выполняет обнаружение лица на изображении.

Это важно. Сначала мне нужно выполнить обнаружение лиц, потому что детектор ориентиров будет работать только в том случае, если я скажу ему, какая часть изображения содержит лицо. Если я запущу детектор ориентиров непосредственно на все изображение, это не сработает.

Итак, теперь переменная faces содержит массив структур Rectangle. Каждый прямоугольник описывает, где детектор лиц обнаружил лицо на изображении.

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

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

Переменная shape теперь содержит набор ориентиров, а shape.Parts - количество точек. Я получаю каждую точку с помощью GetPart, конвертирую ее в прямоугольник и рисую прямо на изображении с помощью Dlib.DrawRectangle.

Последний шаг - сохранить измененное изображение:

При этом используется метод Dlib.SaveJpeg для сохранения изображения как output.jpg.

Вот и все!

Вы можете запустить это приложение в Linux, OS / X или Windows с кодом Visual Studio:

… Или в командной строке с помощью команды dotnet run:

$ dotnet run

А вот выходное изображение:

Это отличный результат. Единственные две знаменитости, которые не были обнаружены, - это Джаред Лето (крайний слева) и Анджелина Джоли (вверху справа сзади). Их лица видны только частично, поэтому детектор лиц Dlib не имеет достаточного количества пикселей для работы.

Теперь посмотрите на Лупиту Нионг’О (вверху справа сзади). Ее лицо видно только частично, но детектор ориентиров угадал расположение всех ее ориентиров, которые скрыты за плечом Брэда Питта.

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

Еще одна приятная особенность детектора ориентиров Dlib - его сверхбыстрая работа. Полное обнаружение занимает всего 1 миллисекунду. Это потрясающая производительность, и это означает, что мы можем отслеживать ориентиры в реальном времени.

Так что ты думаешь? Готовы ли вы начать писать приложения для компьютерного зрения на C # с помощью DlibDotNet?