Лучший язык в мире PHP: я также могу делать компьютерное зрение с OpenCV

PHP HTTPS GitHub OpenCV

Выбрано из Medium Владимира Гончарова, составлено Heart of the Machine.

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

Как и многие разработчики, я часто использую работу других людей (статьи на среднем, код на Github и т. Д.), Так что я рад поделиться своей работой с сообществом. Не только пишет награду за общину, это позволяет вам найти единомышленников, наставлять профессионалы в узком поле, а дальше ваше понимание области обучения.

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

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

Новые подходы к решению конкретных задач часто описываются в недавно опубликованных статьях, а реализации методов можно найти в статьях на GitHub. Так как чаще всего используются языки программирования: C/C++, Python 2/3, Lua и Matlab, а фреймворки: Caffe, TensorFlow, Torch. Так что огромный выбор языков программирования и фреймворков усложняет процесс поиска того, что вам нужно, и интеграции в ваш проект.

Модуль DNN, добавленный в OpenCV, уменьшает эту путаницу таким образом, что позволяет напрямую использовать модель, обученную в базовой структуре. Я покажу вам, как использовать этот модуль в PHP.

Модуль ДНС:GitHub.com/OpenCV/открыть…

Джереми Ховард (Создатель свободных рук на курсе «Машина обучения для кодировщиков») считает, что существует большая линия между учебной машиной и практическим приложением сегодня.

Ховард считает, что года опыта программирования достаточно, чтобы начать изучать машинное обучение. Я полностью с ним согласен, и я надеюсь, что моя статья поможет снизить входной барьер для PHP-разработчиков, которые плохо знакомы с машинным обучением и не уверены, хотят ли они заниматься машинным обучением, и я попытаюсь объяснить, что я потратил Много времени Время получает точку зрения, так что вам даже не нужно много времени, чтобы понять ее.

Логотип проекта php-opencv

Я думал о написании модуля php-opencv с помощью SWIG и потратил на это много времени, но не получил никаких результатов. Все сложно, потому что я не знаю C/C++ и не писал файл расширения для PHP 7. К сожалению, большая часть материала в сети представляет собой расширение PHP на основе PHP 5, поэтому мне пришлось собрать немного информации и разобраться самому.

Затем я нашел на GitHub библиотеку php-opencv, которая представляет собой модуль PHP 7 для вызова методов OpenCV. Я провел несколько ночей, компилируя, устанавливая и запуская примеры. Я начал экспериментировать с разными возможностями этого модуля, но в библиотеке все равно не хватало некоторых методов, поэтому я добавил их сам и создал пулл-реквест, а автор библиотеки их принял. После этого я добавил больше функций.

php-opencv:GitHub.com/Hi Oh Week/Сотрудничество…

Вот как изображение нагрузки:

$image = cv\imread(“images/faces.jpg”);

Напротив, изображение, загруженное в python, таково, что:

image = cv2.imread(“images/faces.jpg”)

При чтении изображения в PHP (и в C++) информация сохраняется в объекте Mat (матрице). В PHP, похожем на многомерный массив, но отличном от него, объект может выполнять несколько быстрых операций, таких как одновременное деление всех элементов на число. В Python при загрузке изображения возвращается объект «NumPy».

Будьте осторожны с исходным действием по умолчанию! Бывает, что imread (в php, c++ и python) загружает изображение не в RGB, а в BGR. Так, в примерах OpenCV часто можно увидеть процесс преобразования BGR в RGB и наоборот.


Распознавание лиц

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

$src = imread(“images/faces.jpg”); 
$gray = cvtColor($src, COLOR_BGR2GRAY); 
$faceClassifier = new CascadeClassifier(); 
$faceClassifier->load(‘models/lbpcascades/lbpcascade_frontalface.xml’); 
$faceClassifier->detectMultiScale($gray, $faces);

Полный тестовый пример кода:GitHub.com/PHP-OpenCV/…


результат:

Как видно из этого примера, человеческое лицо можно найти даже на фото в гриме зомби. Характерные точки не мешают локализации лица.


распознавание лица

Для распознавания лиц в OpenCV есть класс LBPHFaceRecognizer и методы обучения/прогнозирования.

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

$faceRecognizer = LBPHFaceRecognizer :: create ();
$faceRecognizer-> train ($myFaces, $myLabels = [1,1,1,1]); // 4 my faces
$faceRecognizer-> update ($angelinaFaces, $angelinaLabels = [2,2,2,2]); // 4 faces of Angelina
$label = $faceRecognizer-> predict ($faceImage, $confidence);
// get label (1 or 2) and confidence

Полный пример кода:GitHub.com/PHP-OpenCV/…


набор данных:


результат:

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


Маркеры лиц/характерные точки

Когда я начал знакомиться с OpenCV, я часто видел изображения людей с точками, обозначающими глаза, нос, губы и т. д. Я хотел бы повторить этот эксперимент сам, но он не реализован в версии OpenCV для Python. Я провел вечер, добавляя поддержку FacematkLBF в PHP и возвращая объект. Все просто и легко, загружаем предобученную модель, вводим массив лиц и получаем массив характерных точек для каждого человека.

$facemark = FacemarkLBF::create(); 
$facemark->loadModel(‘models/opencv-facemark-lbf/lbfmodel.yaml’); 
$facemark->fit($image, $faces, $landmarks);

Полный пример кода:GitHub.com/PHP-OpenCV/…


результат:

Как видно из этого примера, макияж зомби затрудняет поиск характерных точек на человеческом лице. Характерные точки также могут мешать локализации лиц. Освещение тоже играет роль, в этом случае посторонние предметы во рту (клубника, сигареты и т.д.) могут не мешать.

После моего первого запроса на включение я вдохновился и начал понимать, что может сделать opencv, и наткнулся на статью «Глубокое обучение, теперь в OpenCV». Сразу решил использовать предобученные модели в php-opencv, их много в инете. Хотя позже я потратил много времени на то, чтобы научиться работать с многомерными матрицами и использовать модели Caffe/Torch/TensorFlow без OpenCV, загрузить модель Caffe оказалось несложно.

Глубокое обучение, теперь в OpenCV:GitHub.com/OpenCV/открыть…


Обнаружение лиц с использованием моделей DNN

Поэтому OpenCV позволяет загружать предварительно обученные модели в Caffe с помощью функции readNetFromCaffe. Он принимает два параметра: пути к файлам .prototxt и .caffemodel. В файле prototxt есть описание модели, а в caffemodel — веса, вычисленные во время обучения модели.

Ниже приведен пример файла prototxt:

input:“data”
input_shape { 
 dim: 1 
 dim: 3 
 dim: 300 
 dim: 300 
}

Этот файл описывает ввод 4-мерной матрицы размером 1x3x300x300. В описании модели обычно указано, что значит вводить в этом формате, но в большинстве случаев это означает, что на вход будет входить RGB-изображение (3 канала) размером 300х300.

Загружая RGB-изображение 300х300 с помощью функции imread, мы получаем матрицу 300х300х3.

В OpenCV есть функция blobFromImage, которая преобразует матрицу 300x300x3 в формат 1x3x300x300.

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

$src = imread(“images/faces.jpg”); 
$net = \CV\DNN\readNetFromCaffe(‘models/ssd/res10_300x300_ssd_deploy.prototxt’, ‘models/ssd/res10_300x300_ssd_iter_140000.caffemodel’); 
$blob = \CV\DNN\blobFromImage($src, $scalefactor = 1.0, $size = new Size(300, 300), $mean = new Scalar(104, 177, 123), $swapRB = true, $crop = false); 
$net->setInput($blob,“”); 
$result = $net->forward();

В этом примере результатом является матрица 1x1x200x7, т.е. 200 массивов по 7 элементов на изображение. На фото с 4 лицами сеть нашла 200 кандидатов. Каждый из этих объектов имеет вид [$confidence, $startX, $startY, $endX, $endY]. Элемент $confidence представляет «доверие», то есть насколько хороша прогнозируемая вероятность, например, 0,75 — это хорошо. Элементы после этого представляют координаты прямоугольника лица. В этом примере только 3 лица были найдены с достоверностью более 50%, а остальные 197 кандидатов были найдены с достоверностью менее 15%.

Полный пример кода:GitHub.com/PHP-OpenCV/…


результат:

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


Использование нейронных сетей для улучшения качества изображения

Давным-давно я слышал о библиотеке waifu2x, которая убирает шумы и увеличивает размер иконок/фото. Библиотека написана на lua и использует несколько моделей, обученных на Torch под капотом (чтобы увеличить размер иконок, убрать фотошумы и т.д.). Автор этой библиотеки экспортировал эти модели в Caffe и помог мне использовать их в OpenCV. Таким примером может быть что-то, написанное на PHP для увеличения разрешения значка.

Увеличить картинку без использования нейронной сети

классификация изображений

Нейронная сеть MobileNet, обученная на ImageNet, может классифицировать изображения. Всего он может выделить 1000 категорий, что мне мало.

Полный код примера:GitHub.com/PHP-OpenCV/…

Результат: 87% - египетский кот, 4% - кошка, 2% - тигровый кот

Tensorflow целевой обнаружение API

Сеть MobileNet SSD (Single Shot MultiBox Detector), обученная с помощью Tensorflow на наборе данных COCO, может не только классифицировать изображения, но и возвращать области объектов, хотя можно обнаружить только 182 класса.

Полный код примера:GitHub.com/PHP-OpenCV/…

исходное изображение
результат

Выделение синтаксиса и завершение кода

Я также добавил файлы phpdoc.php в репозиторий и в качестве примера. Благодаря этому PHPSTORM подсвечивает синтаксис, классы и методы функции, а также может использоваться для автодополнения кода. Этот файл не нужно включать в свой код (иначе появится ошибка), достаточно поставить его в свой проект. Лично мне это упрощает программирование. Этот файл описывает большую часть функций OpenCV, но не все, так что добро пожаловать, чтобы отправить запрос на извлечение.

phpdoc.php:GitHub.com/PHP-OpenCV/…


Установить

Модуль «dnn» присутствует только в OpenCV 3.4 (в предыдущих версиях он был в contrib).

Последняя версия OpenCV для Ubuntu 18.04 — 3.2. Сборка OpenCV из исходников занимает около получаса, поэтому я скомпилировал этот пакет под Ubuntu 18.04 (также для 17.10, размер 25 МБ) как для PHP 7.2 (Ubuntu 18.04), так и для PHP 7.1 (Ubuntu 17.10) (размер 100 КБ), скомпилировал Пакет php-opencv. Зарегистрировал ppa: php-opencv, но еще не закончил его заливать и не нашел ничего лучше, чем залить пакет на GitHub. Я также создал запрос на создание учетной записи в pecl, но не получил ответа в течение нескольких месяцев.

Загрузите пакеты на Github:GitHub.com/PHP-OpenCV/…

Итак, теперь установка под Ubuntu 18.04 выглядит так:

apt update && apt install -y wget && \
wget https://raw.githubusercontent.com/php-opencv/php-opencv-packages/master/opencv_3.4_amd64.deb && dpkg -i opencv_3.4_amd64.deb && rm opencv_3.4_amd64.deb && \
wget https://raw.githubusercontent.com/php-opencv/php-opencv-packages/master/php-opencv_7.2-3.4_amd64.deb && dpkg -i php-opencv_7.2–3.4_amd64.deb && rm php-opencv_7.2–3.4_amd64.deb && \
echo“extension=opencv.so”> /etc/php/7.2/cli/conf.d/opencv.ini

Установка этой опции занимает около 1 минуты, все варианты установки выполняются в Ubuntu:GitHub.com/PHP-OpenCV/…

Я также скомпилировал образ докера размером 168 МБ.


Пример использования

скачать:

git clone https://github.com/php-opencv/php-opencv-examples.git && cd php-opencv-examples

бегать:

php detect_face_by_dnn_ssd.php


Оригинальная ссылка:medium.com/@default O означает o против K/…