Обучение каскада Хаара на примере поиска символов автомобильного номера OpenCV

Поиска объекта на цифровом изображении одна из приоритетных задач в области распознавания изображений с помощью библиотеки OpenCV.

В данной статье рассматриваются математические основы Метода Виолы-Джонса и процесс поиска и распознавания букв автомобильного номера с помощью OpenCV и детектора Хаара.

О детекторе Хаара и библиотеке OpenCV

Основное преимущество детектора Хаара: скорость. Благодаря быстрой обработки изображения, можно с лёгкостью обрабатывать потоковое видео. Детектор Хаара используется для распознавания большинства классов объектов. К ним относятся лица и другие части тела людей, номера автомобилей, пешеходы, дорожные знаки, животные и.т.д. Детектор Хаара реализован в библиотеке OpenCV . Это даёт огромное преимущество. Так как готовые реализации OpenCV есть под большинство существующих операционных систем(Android, Windows, Linux, ios).

Принцип работы

Классификатор формируется на примитивах Хаара путём расчёта значений признаков. Для обучения на вход классификатора сначала подаётся набор «правильных» изображений с предварительно выделенной областью на изображении, дальше происходит перебор примитивов и расчёт значения признака. Вычисленные значения сохраняются в файле в формате xml.



Немного математики

Принципы метода Виолы-Джонса

В настоящее время метод Виолы–Джонса является популярным методом для поиска объекта на изображении в силу своей высокой скорости и эффективности. В основу метода Виолы–Джонса положены: интегральное представление изображения по признакам Хаара, построение классификатора на основе алгоритма адаптивного бустинга и способ комбинирования классификаторов в каскадную структуру. Эти идеи позволяют осуществлять поиск объекта в режиме реального времени. Рассмотрим их более подробно.

Интегральное представление изображения – это матрица, одинаковая по размерам с исходным изображением. В каждом элементе матрицы хранится сумма интенсивностей всех пикселов, находящихся левее и выше данного элемента – правого нижнего угла прямоугольной области (0,0) до (x,y). Элементы матрицы L можно рассчитать по формуле:

 

где I(i,j) – яркость пиксела исходного изображения.

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

Элементы матрицы рассчитываются по формуле:

L(x,y)= I(x,y)+ L(x-1,y-1) + L(x,y-1) + L(x-1,y)

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

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

Признак-отображение , где Df —множество допустимых значений признака. Если заданы признаки f1,…, fn, то вектор признаков x=(f1(x),…,fn(x)) называется признаковым описанием объекта x. Признаковые описания допустимо сопоставлять с самими объектами. При этом множество X=Df1*…*Dfn называют признаковым пространством [1].

Признаки делятся на следующие типы в зависимости от множества Df:

  • бинарный признак, Df={0,1};
  • номинальный признак: Df — конечное множество;
  • порядковый признак: Df — конечное упорядоченное множество;
  • количественный признак: Df — множество действительных чисел.

Признак Хаара вычисляется по смежным прямоугольным областям. В стандартном методе Виолы–Джонса используются прямоугольные примитивы, изображенные на рисунке 1.

Рисунок 1 – Примитивы Хаара

Рисунок 1

Вычисляемым значением F признака Хаара будет

F = X — Y,

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

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

Классификатор строится на основе алгоритма бустинга (от англ.boost–улучшение, усиление) для выбора наиболее подходящих признаков для искомого объекта на данной части изображения. В общем случае бустинг — это комплекс методов, способствующих повышению точности аналитических моделей. Эффективная модель, допускающая мало ошибок классификации, называется «сильной». «Слабая» же, напротив, не позволяет надежно разделять классы или давать точные предсказания, делает большое количество ошибок. Поэтому бустинг означает «усиление» «слабых» моделей и является процедурой последовательного построения композиции алгоритмов машинного обучения, когда каждый следующий алгоритм стремится компенсировать недостатки композиции всех предыдущих алгоритмов.

В результате работы алгоритма бустинга на каждой итерации формируется простой классификатор вида:

 p_j– направление знака неравенства,  θ_j— значение порога, f_j(z)– вычисленное значение признака, z – окно изображения размером 24×24 пикселов.

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

Для поиска объекта на цифровом изображении используется обученный классификатор, представленный в формате xml. Классификатор формируется на примитивах Хаара.

Структура классификатора:

где maxWeakCount количество слабых классификаторов;

stageThereshold максимальный порог яркости;

weakClassifiers набор слабых классификаторов, на основе которых выносится решение о том, находится объект на изображении или нет;

internalNodes и leafValues  параметры конкретного слабого классификатора.

Первые два значения в internalNodes не используются, третье — номер признака в общей таблице признаков (она располагается в XML-файле под тегом features), четвертое — пороговое значение слабого классификатора. Если значение признака Хаара меньше порога слабого классификатора, выбирается первое значение leafValues, если больше — второе.

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

Обучение каскада Хаара

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

Классификатор формируется на примитивах Хаара путём расчёта значений признаков. Для обучения на вход классификатора сначала подаётся набор «правильных» изображений с предварительно выделенной областью автомобильного номера, дальше происходит перебор примитивов и расчёт значения признака. Вычисленные значения сохраняются в файле в формате xml.

Утилита для обучения каскада Хаара встроена в пакет OpenCV.

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

Список:
  • Реальные фотографии объекта. Чем более похожа выборка будет на то, что мы будем распознавать, тем лучше будут результаты. Если обучать распознаватель лица по фотографиям людей из студии, то на улице уровень распознавания будет ниже, чем в студии. На это влияют как тени, одежда, так и выражение лица.
  • Выборка отрицательных фотографий, на которых нет объекта распознавания. Фотографии должны быть сделаны в той же среде где будет распознавание. Если выборка контрпримеров будет сделана по фотографиям на северном полюсе, а распознавать будете в тропических джунглях, то ничего не заработает.
Сколько нужно фотографий?

Для стабильно работающего детектора лиц это 3000-4000 положительных примеров и столько же отрицательных. Из 500 положительных и 1000 отрицательных мои коллеги делали стабильный детектор номеров. Для детектора, который показан в этой статье, я взял 500 положительных и 500 негативных фотографий.
Чем больше и разнообразнее выборка, тем стабильнее работает и тем дольше обучается.

Начнём

Для начала нам нужно сформировать папку с положительными и отрицательными фотографиями. Для данной цели я использовал программу Picture Cropper скачать. Работа с программой: мышкой выделяется область которая должна быть сохранена. По «s» происходит сохранение. По «r» – сохранение и переход к следующему изображению. По пробелу — просто переход к следующему изображению.

Для обучения нам нужно иметь 2 папки с примерами. «Good» — папка с позитивными изображениями, «Bad» — с отрицательными. Стоит учесть, что OpenCV отказывается работать с точками, пробелами и спец. символами. Не используйте данные символы в названиях примеров. Идеальные названия: «0.bmp», «1. bmp» и.т.д.

Для каждой папки с примерами необходимо иметь файл описания, в котором описаны используемые изображения. Стандартно их называют «Good.dat» и «Bad.dat».

Файлы должны лежать на одном уровне с папками.

Пример иерархии:

Файлы описания для отрицательных и положительных объектов имеют разную структуру. Для файла отрицательных примеров это просто список относительных путей к изображениям:

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

«Good \0.bmp» — адрес объекта относительно файла описания. «1» — количество положительных объектов на изображении. «0 0 414 148» — координаты прямоугольника на изображении в котором находится объект. Если объектов несколько, то запись приобретает вид: «Good \0.bmp 2 100 200 50 50 300 300 25 25».
Удобнее всего, когда каждый объект представляет собой отдельный кадр, при этом координаты объекта равны размеру кадра.

Пример создания Good.dat и Bad.dat на примере работы с Picture Cropper

  1. Создаём папку, к примеру «Learn».
  2. Создаём под папки: Good, Bad.
  3. Распаковываем Picture Cropper
  4. Перекидываем в папку Good, изображения с объектом. (Цельные, не обрезанные)

В итоге у нас должна получиться следующая структура:

Кладём в папку Good и Bad необходимые файлы.

Запускаем PictureCropper.exe.

Выбираем нужную папку и обрабатываем изображения.

Работа с программой: мышкой выделяется область которая должна быть сохранена. По «s» происходит сохранение. По «r» – сохранение и переход к следующему изображению. По пробелу — просто переход к следующему изображению.

После завершения работы у нас должен появиться Good.dat. И в папке Good папка Cropper, в которой хранятся обрезанные изображения.

Отлично. Проделываем тоже самое с папкой Bad.

После процедуры обработки фотографий в папке Bad, приведём его файл описания Bad.dat к «правильному виду».

Сейчас файл Bad.dat выглядит следующим образом:

Приводим его к нужному формату:

На этом работа с файлами описания закончена.

Переходим к обучению.

Для начала откроем командную строку и перейдём в директорию с файлом описания Good.dat, то есть в папку learn:

Для создания пачки приведённых положительных изображений запустим opencv_createsamples через консоль:

Good.dat – файл описания положительных изображений. Указывается либо полный адрес, либо относительно программы opencv_createsamples.exe.
-vec samples.vec – файл, в который будет сохранена приведённая к общему формату база положительных изображений. Адрес должен быть указан относительно программы opencv_createsamples.exe (допустим полный путь в системе).
-w 20 -h 30 — размер шаблона. Должен приблизительно отражать пропорции искомого объекта. Например, для лиц или для символа автомобильного номера наиболее подходящая пропорция высоты к ширине 1*3. Для номеров это 3*1. А для поиска карандаша логично поставить что-то вроде 8*1. Размер шаблона должен быть достаточно маленьким. Идеально ставить его таким, чтобы человек сам мог отличить изображённый объект, но не больше того. Чем больше шаблон, тем дольше обучение.
Результатом работы программы является файл samples.vec, в котором будут лежать все ваши положительные изображения в формате, близком к bmp и с размером w*h.

Если всё прошло успешно должен появиться файл samples.vec.

Созданием основного каскада:

Для подсчёта итогового каскада используется программа «opencv_traincascade.exe», лежащая в той же папке, что и opencv_createsamples.exe. Работает долго. Даже очень долго. Обучение каскада на 500-1000 объектов займёт почти целый день. Пример обучался часа 24. При вызове:

-data haarcascade — адрес папки, куда класть полученные результаты. Отсчитывается от корневой папки программы. Нужно создать заранее, а то всё вылетит.
-vec samples.vec — адрес посчитанного в прошлом пункте файла с положительными примерами
-bg Bad.dat — адрес файла-описания отрицательных примеров
-numStages 16 — количество уровней каскада, которые программа будет обучать. Чем больше уровней, тем точнее, но тем дольше. Нормальное их количество от 16 до 25.
-minhitrate 0.999 — коэффициент, определяющий качество обучения. По сути, это процент “правильных” обнаружений. Если установлено .999, то есть по исходной выборке будет не более, чем 1- 0.999 =0.1% пропусков целей. Чем выше коэффициент, тем выше уровень ложных тревог. В принципе, если выборка хорошая, можно ставить 0.99-0.999. Если плохая ( объектов мало, они смешиваются с фоном) — то следует опускать.
-maxFalseAlarmRate 0.4 — уровень ложной тревоги. AdaBoost — такой алгоритм, который может любой уровень ложной тревоги по выборке натянуть. Но лучше что-то разумное сделать. По умолчанию все ставят 0.5. Но, возможно, будет иметь смысл поиграться. В случае, если выборка очень хорошая, то уровень требуемой тревоги будет быстро достигнут, и обучение будет остановлено.
-numPos 400 — количество позитивных примеров. ВАЖНО! Казалось бы, тут должно стоять число файлов, которые у вас были. Но это не так (в большинстве руководств это не отмечено). Чем ниже коэффициент «minhitrate», тем больше ваших файлов будет считаться непригодными. В большинстве случаев достаточно поставить numPos 80% от имеющихся у вас положительных файлов. Лучше перестраховаться, чтобы через день работы программа не вылетела с ошибкой:)
-numNeg 500 — количество имеющихся у вас негативных примеров. Что есть — то и пишем.
-w 20 -h 30 — размер примитива из прошлого пункта.
-mode ALL — использовать или нет полный комплект Хаар-признаков. От этого зависит скорость работы и точность алгоритма. Но есть ситуации, когда полного комплекта признаков не нужно (например, если ваш объект не меняет ориентацию).
-precalcValBufSize 256 -precalcIdxBufSize 256 — выделяемая под процесс память. Вроде, в последней версии OpenCV, сколько я заявил, примерно столько программа и съела, но чуть более ранние версии ели где-то в 2 раза больше. Если во время обучения вы планируете пользоваться компьютером, то ставьте столько памяти, чтобы вам хватило на дальнейшую работу.

После того, как алгоритм закончит работу, у вас появится папка haarcascade и файл cascade.xml в этой папке, это и будет созданный каскад.

Пример выполнения:

Напишем простую программу на OpenCV для демонстрации работы алгоритма:

На этом тестирование алгоритма закончено.

Использованная литература:

http://habrahabr.ru/post/208092/

 

6 Комментарии “Обучение каскада Хаара на примере поиска символов автомобильного номера OpenCV

  1. Можно ли скинуть ссылку на готовую программу ? не получается подключить нормально библиотеки чтобы скомпилировать проект. хотелось бы попробовать.

  2. судя по скрину при приведении у меня относительно тоже самое но файл vec не появляется

    1. То же самое только что было — зайдите в папку пользователя (Users), если Вы под Windiws

  3. У меня почему то не начинается обучение (opencv_traincascade.exe).

    Пишет: Train dataset for temp stage can not be filled. Branch training terminated. Cascade classifier can’t be trained. Check the use training parameters.

    В чем может быть проблема?

Добавить комментарий

Ваш e-mail не будет опубликован.