Версия:
Аннотация
Преобразование растровых изображений в бинарные. Пороговые функции. Связанные компоненты. Их подсчет.
В данной заметке будет показано как выделять контура у объектов на бинарном изображении. Далее показано, как их аппроксимировать аналитическими кривыми: линия, окружность и тому подобное.
Выделение контуров и их иерархию. В целом для их выделения используется функция findContours, но в зависимости от конкретной задачи с разными параметрами.
Напомню, что мы придерживаемся идеологии, что у нас есть фон и есть объекты. У объекта можно выделить внешний контур, а также внутренний (там где дырки). В общем случае можно построить иерархию объектов.
Выделение внешних контуров Напомню, как считать и превратить цветное изображение в бинарное:
Далее, для выделения только внешних контуров на изображение используется такой код: что это делается так:
Наиболее важна для нас переменная contours. Переменная hierarchy будет использована в следующих параграфах.
В contours хранятся выделенные контура объекта. При вызове было задано RETR_EXTERNAL поэтому будут выделены только внешние контура объектов.
Параметр CHAIN_APPROX_SIMPLE указывает на то, что подряд идущие точки по горизонтали и вертикали не следует записывать в контур (для экономии памяти). Если указать значение HAIN_APPROX_NONE , то будут указаны все точки контура (согласно идеологии 8-связанности).
Итого, размер вектора contours указывает на количество связанных компонент.
Исходя их определения переменной contours следует, что её элементы в свою очередь также являются векторами типа vector<Point2i>, т.е. состоят из точек. Поэтому, contours[i][j] задает координаты ой точки го контура.
Упражнение. Напиши программу, которая отрисовывает контура (разными цветами).
Отрисовка контуров Отрисовать контура можно и использую, соответствующую, функцию опенсв: drawContours.
Первый аргумент указывает на изображение на котором будет выполнена отрисовка контуров. Второй аргумент задает сами контура. Третий на индекс контура, который нужно отрисовать. В случае, если задать число будут отрисованы все контура. Далее задается цвет и толщина линий (отрезков).
Выделение внутренних контуров Далее рассмотрим как выделять дырки в объектах. Заменем параметр RETR_EXTERNAL на RETR_CCOMP.
Последний параметр позволяет создать простейшую иерархию их контуров. Он помимо внешнего контура объекта выделяет и внутренние, т.е. ищет дырки. Данная информация занесена в переменную hierarchy. Рассмотрем её подробнее для понимания того как это происходит.
Каждый из элементов вектора hierarchy (имея тип Vec4i) состоит из 4 целочисленных компонент. Он имеет такой же размер, что и вектор контуров (contours). Фактически в переменной hierarchy для каждого контура хранится его положение в иерархии контуров, т.е. какие у него соседние дыры (братья/сестры), дыры (дети) и родитель. Так, все компоненты являются индексами. Индекс равный означает отсутствие данной сущности. Итого, компоненты указывают на индекс:
В случае использования параметра RETR_CCOMP иерархия устроена просто. Для каждого внешнего контура указаны контура дыр в случае их наличия.
Определение иерархии Для полноценного разбора всех контуров необходимо заменить в первоначальном вызове параметр RETR_EXTERNAL на RETR_TREE, т.е. сделать вызов следующим образом:
При таком вызове в переменной hierarchy хранится полноценная информация об иерархии контуров: в ней для каждой дыры хранится контура которые в ней находятся.
Напишем функцию, которая печатает эту иерархию:
Вызвать эту функцию следует следующим образом:
Упражнение. Напишите программу, которая на изображении выделает все контура, которые содержать две дырки и одну дырку с объектом.
Можно применить и моменты пройденные ранее.
После того как контура выделены их можно аппроксимировать аналитическими кривыми.
approxPolyDP
Эллипс fitEllipseAMS fitEllipseDirect
boundingRect minAreaRect
minEnclosingCircle minEnclosingTriangle