Учебное пособие по OpenCV: обнаружение объектов в реальном времени с использованием MSER в iOS

Опубликовано: 2022-03-11

За последние несколько лет средняя производительность мобильного телефона значительно увеличилась. Будь то чистая мощность процессора или объем оперативной памяти, теперь выполнять сложные вычислительные задачи на мобильном оборудовании стало проще. Хотя эти мобильные технологии движутся в правильном направлении, на мобильных платформах еще многое предстоит сделать, особенно с появлением дополненной реальности, виртуальной реальности и искусственного интеллекта.

Основной задачей компьютерного зрения является обнаружение объектов интереса на изображениях. Человеческий глаз и мозг делают исключительную работу, и воспроизвести это в машинах — пока мечта. За последние десятилетия были разработаны подходы к имитации этого в машинах, и они становятся все лучше.

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

Учебник по OpenCV

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

OpenCV написан на C/C++ и имеет библиотеки-оболочки для всех основных платформ. Это делает его особенно простым в использовании в среде iOS. Чтобы использовать его в iOS-приложении Objective-C, загрузите OpenCV iOS Framework с официального сайта. Пожалуйста, убедитесь, что вы используете версию 2.4.11 OpenCV для iOS (которую вы используете в этой статье), так как последняя версия 3.0 имеет некоторые нарушающие совместимость изменения в организации файлов заголовков. Подробная информация о том, как его установить, задокументирована на его веб-сайте.

МСЭР

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

Хотя существует ряд других алгоритмов обнаружения больших двоичных объектов, здесь был выбран MSER, потому что он имеет довольно небольшую сложность времени выполнения O(n log(log(n))), где n — общее количество пикселей на изображении. Алгоритм также устойчив к размытию и масштабированию, что является преимуществом, когда речь идет об обработке изображений, полученных из источников реального времени, таких как камера мобильного телефона.

Для целей этого руководства мы разработаем приложение для обнаружения логотипа Toptal. Символ имеет острые углы, и это может навести на мысль о том, насколько эффективными могут быть алгоритмы обнаружения углов при обнаружении логотипа Toptal. Ведь такой алгоритм и прост в использовании, и в понимании. Хотя методы на основе углов могут иметь высокий уровень успеха, когда речь идет об обнаружении объектов, которые отчетливо отделены от фона (например, черные объекты на белом фоне), было бы трудно добиться обнаружения логотипа Toptal в реальном времени в реальном мире. изображений, где алгоритм будет постоянно обнаруживать сотни углов.

Стратегия

машинное обучение и opencv

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

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

Кроме того, для каждого MSER вычисляется ряд свойств:

  • Количество отверстий
  • Отношение площади МСЭР к площади его выпуклой оболочки
  • Отношение площади MSER к площади его прямоугольника минимальной площади
  • Отношение длины скелета МСЭР к площади МСЭР
  • Отношение площади МСЭР к площади ее наибольшего контура

iOS-приложения и машинное обучение

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

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

iOS-приложение

Использовать OpenCV из iOS очень просто. Если вы еще этого не сделали, вот краткий обзор шагов, связанных с настройкой Xcode для создания приложения iOS и использования в нем OpenCV:

  1. Создайте новый проект под названием «Детектор логотипов SuperCool». В качестве языка оставьте выбранным Objective-C.

  2. Добавьте новый файл заголовка префикса (.pch) и назовите его PrefixHeader.pch.

  3. Перейдите в цель сборки проекта «SuperCool Logo Detector» и на вкладке «Параметры сборки» найдите параметр «Заголовки префиксов». Вы можете найти его в разделе Язык LLVM или воспользоваться функцией поиска.

  4. Добавьте «PrefixHeader.pch» в настройку заголовков префикса.

  5. На данный момент, если вы еще не установили OpenCV для iOS 2.4.11, сделайте это сейчас.

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

  7. Кроме того, свяжите следующие фреймворки:

    • AVFoundation
    • АктивыБиблиотека
    • CoreMedia
  8. Откройте «PrefixHeader.pch» и добавьте следующие 3 строки:

     #ifdef __cplusplus #include <opencv2/opencv.hpp> #endif”
  9. Измените расширения автоматически созданных файлов кода с « .m» на « .mm». OpenCV написан на C++, а с *.mm вы говорите, что будете использовать Objective-C++.

  10. Импортируйте «opencv2/highgui/cap_ios.h» в ViewController.h и измените ViewController, чтобы он соответствовал протоколу CvVideoCameraDelegate:

     #import <opencv2/highgui/cap_ios.h>
  11. Откройте Main.storyboard и поместите UIImageView на начальный контроллер представления.

  12. Сделайте выход в ViewController.mm с именем «imageView».

  13. Создайте переменную «CvVideoCamera *camera;» в ViewController.h или ViewController.mm и инициализируйте его ссылкой на заднюю камеру:

     camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
  14. Если вы создадите проект сейчас, Xcode предупредит вас, что вы не реализовали метод «processImage» из CvVideoCameraDelegate. Сейчас для простоты мы просто получим изображения с камеры и наложим на них простой текст:

    • Добавьте одну строку в «viewDidAppear»:
     [camera start];
    • Теперь, если вы запустите приложение, оно запросит у вас разрешение на доступ к камере. И тогда вы должны увидеть видео с камеры.

    • В методе «processImage» добавьте следующие две строки:

     const char* str = [@"Toptal" cStringUsingEncoding: NSUTF8StringEncoding]; cv::putText(image, str, cv::Point(100, 100), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 255));

Вот и все. Теперь у вас есть очень простое приложение, которое рисует текст «Toptal» на изображениях с камеры. Теперь мы можем создать наше целевое приложение для обнаружения логотипа на основе этого более простого. Для краткости в этой статье мы обсудим лишь несколько сегментов кода, которые имеют решающее значение для понимания того, как работает приложение в целом. В коде на GitHub достаточно комментариев, поясняющих, что делает каждый сегмент.

Поскольку у приложения есть только одна цель - обнаружить логотип Toptal, как только оно запускается, функции MSER извлекаются из заданного изображения шаблона, а значения сохраняются в памяти:

 cv::Mat logo = [ImageUtils cvMatFromUIImage: templateImage]; //get gray image cv::Mat gray; cvtColor(logo, gray, CV_BGRA2GRAY); //mser with maximum area is std::vector<cv::Point> maxMser = [ImageUtils maxMser: &gray]; //get 4 vertices of the maxMSER minrect cv::RotatedRect rect = cv::minAreaRect(maxMser); cv::Point2f points[4]; rect.points(points); //normalize image cv::Mat M = [GeometryUtil getPerspectiveMatrix: points toSize: rect.size]; cv::Mat normalizedImage = [GeometryUtil normalizeImage: &gray withTranformationMatrix: &M withSize: rect.size.width]; //get maxMser from normalized image std::vector<cv::Point> normalizedMser = [ImageUtils maxMser: &normalizedImage]; //remember the template self.logoTemplate = [[MSERManager sharedInstance] extractFeature: &normalizedMser]; //store the feature [self storeTemplate];

Приложение имеет только один экран с кнопкой Start/Stop, а вся необходимая информация, как FPS и количество обнаруженных MSER, автоматически рисуется на изображении. Пока приложение не остановлено, для каждого кадра изображения в камере вызывается следующий метод processImage:

 -(void)processImage:(cv::Mat &)image { cv::Mat gray; cvtColor(image, gray, CV_BGRA2GRAY); std::vector<std::vector<cv::Point>> msers; [[MSERManager sharedInstance] detectRegions: gray intoVector: msers]; if (msers.size() == 0) { return; }; std::vector<cv::Point> *bestMser = nil; double bestPoint = 10.0; std::for_each(msers.begin(), msers.end(), [&] (std::vector<cv::Point> &mser) { MSERFeature *feature = [[MSERManager sharedInstance] extractFeature: &mser]; if(feature != nil) { if([[MLManager sharedInstance] isToptalLogo: feature] ) { double tmp = [[MLManager sharedInstance] distance: feature ]; if ( bestPoint > tmp ) { bestPoint = tmp; bestMser = &mser; } } } }); if (bestMser) { NSLog(@"minDist: %f", bestPoint); cv::Rect bound = cv::boundingRect(*bestMser); cv::rectangle(image, bound, GREEN, 3); } else { cv::rectangle(image, cv::Rect(0, 0, W, H), RED, 3); } // Omitted debug code [FPS draw: image]; }

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

Ниже приведены определения нескольких важных классов и их методов в этом приложении. Их назначение описано в комментариях.

GeometryUtil.h

 /* This static class provides perspective transformation function */ @interface GeometryUtil : NSObject /* Return perspective transformation matrix for given points to square with origin [0,0] and with size (size.width, size.width) */ + (cv::Mat) getPerspectiveMatrix: (cv::Point2f[]) points toSize: (cv::Size2f) size; /* Returns new perspecivly transformed image with given size */ + (cv::Mat) normalizeImage: (cv::Mat *) image withTranformationMatrix: (cv::Mat *) M withSize: (float) size; @end

MSERManager.h

 /* Singelton class providing function related to msers */ @interface MSERManager : NSObject + (MSERManager *) sharedInstance; /* Extracts all msers into provided vector */ - (void) detectRegions: (cv::Mat &) gray intoVector: (std::vector<std::vector<cv::Point>> &) vector; /* Extracts feature from the mser. For some MSERs feature can be NULL !!! */ - (MSERFeature *) extractFeature: (std::vector<cv::Point> *) mser; @end

MLManager.h

 /* This singleton class wraps object recognition function */ @interface MLManager : NSObject + (MLManager *) sharedInstance; /* Stores feature from the biggest MSER in the templateImage */ - (void) learn: (UIImage *) templateImage; /* Sum of the differences between logo feature and given feature */ - (double) distance: (MSERFeature *) feature; /* Returns true if the given feature is similar to the one learned from the template */ - (BOOL) isToptalLogo: (MSERFeature *) feature; @end

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

Обнаружение изображения (логотипа Toptal) по вертикали.

Обнаружение изображения (логотипа Toptal) по диагонали на рубашке.

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

Заключение

В этой статье мы показали, как легко обнаруживать простые объекты на изображении с помощью OpenCV. Весь код доступен на GitHub. Не стесняйтесь разветвлять и отправлять push-запросы, так как вклад приветствуется.

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

Дальнейшее чтение

  • Дж. Матас, О. Чам, М. Урбан и Т. Пайдла. «Надежное широкое базовое стерео из максимально стабильных экстремальных областей».
  • Нойманн, Лукас; Матас, Иржи (2011). «Метод локализации и распознавания текста на изображениях реального мира»
Связанный: Вводный учебник по программированию роботов