Распознавание образов для программистов

ВНИМАНИЕ! БЛОГ ПЕРЕЕХАЛ ПО АДРЕСУ
RECOG.RU

19 Декабрь 2009

8. Использование контуров

написано в рубрике: OpenCV — Кручинин Александр @ 6:56 ДП

Одним из важнейших методов распознавания графических образов является контурный анализ. Библиотека OpenCV предоставляет возможность разработчикам легко детектировать контуры изображения и манипулировать ими. Для поиска контуров предлагается использовать функцию cvFindContours().

 

cvFindContours

 

int cvFindContours(

CvArr* image,

CvMemStorage* storage,

CvSeq** first_contour,

int header_size=sizeof(CvContour),

int mode=CV_RETR_LIST,

int method=CV_CHAIN_APPROX_SIMPLE,

CvPoint offset=cvPoint(0,0)

);

 

Параметры:

image

Исходное 8-битное изображение. Отличные от нуля пикселы обрабатываются как 1, нулевые пикселы остаются 0 – т.е. изображение является монохромным. Чтобы получить такое изображение, можно использовать cvThreshold, cvAdaptiveThreshold или cvCanny. Функция изменяет исходное содержание изображения.

storage

Контейнер найденных контуров.

first_contour

Указатель на первый найденный контур.

header_size

Размер заголовка последовательности, > = sizeof (CvChain) если method=CV_CHAIN_CODE, и > =sizeof (CvContour) в противном случае.

mode

CV_RETR_EXTERNAL – находятся только критические внешние контуры;

CV_RETR_LIST – находятся все контуры, и помещает их в список

CV_RETR_CCOMP – находятся все контуры, и записывают их в иерархию с двумя уровнями: верхний уровень – внешние границы компонентов, второй уровень – границы отверстий

CV_RETR_TREE – находятся все контуры, и записывается полная иерархия вложенных контуров.

method

Метод аппроксимации (для всех режимов, кроме CV_RETR_RUNS, который использует встроенную аппроксимацию).

CV_CHAIN_CODE – на выходе очерчивает контур в цепном коде Фримена [1]. Все другие методы выводят многоугольники;

CV_CHAIN_APPROX_NONE – переводит все точки с цепного кода в точки;

CV_CHAIN_APPROX_SIMPLE – сжимает горизонтальные, вертикальные, и диагональные доли;

CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS – применяет одну из разновидностей алгоритма апроксимации цепочки Teh-Chin.

CV_LINK_RUNS – использует полностью различный алгоритм поиска контура через соединение горизонтальных долей. Только CV_RETR_LIST режим поиска может использоваться с этим методом.

offset

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

 

Функция cvFindContours отыскивает контуры от монохромного изображения и возвращает число найденных контуров. Указатель first_contour заполняется функцией. Он будет содержать указатель на первый наиболее внешний контур или ПУСТОЙ УКАЗАТЕЛЬ, если никакие контуры не обнаружены (если изображение полностью черно). Другие контуры могут быть достигнуты от first_contour, используя h_next и связей v_next. Последовательность контуров описана интересной структурой CvSeq, которая предоставляет интерфейс для всех динамических структур в OpenCV.

 

CvSeq

 

#define CV_SEQUENCE_FIELDS() \

int flags; /* разные флажки*/ \

int header_size; /* размер заголовка последовательности*/ \

struct CvSeq* h_prev; /* предыдущая последовательность*/ \

struct CvSeq* h_next; /* следующая последовательность*/ \

struct CvSeq* v_prev; /* 2-ая предыдущая последовательность*/ \

struct CvSeq* v_next; /* 2-ая следующая последовательность */ \

int total; /* общее количество элементов */ \

int elem_size;/* размер элемента последовательности в байтах */ \

char* block_max;/* maximal bound of the last block */ \

char* ptr; /* текущий указатель записи */ \

int delta_elems; /* сколько дополнительных элементов для роста последовательности */ \

CvMemStorage* storage; /* где сохранена последовательность*/ \

CvSeqBlock* free_blocks; /* свободные блоки в списке*/ \

CvSeqBlock* first; /* указатель на первую последовательность */

 

typedef struct CvSeq

{

CV_SEQUENCE_FIELDS()

} CvSeq;

 

После того, как контуры обнаружены – их можно вывести в изображению с помощью функции cvDrawContours().

 

cvDrawContours

 

void cvDrawContours(

CvArr *img,

CvSeq* contour,

CvScalar external_color,

CvScalar hole_color,

int max_level,

int thickness=1,

int line_type=8,

CvPoint offset=cvPoint(0,0)

);

 

Параметры:

img

Изображение, в которое будут выводиться контуры.

contour

Указатель на первый контур.

external_color

Цвет внешних контуров.

hole_color

Цвет внутренних контуров.

max_level 

Максимальный уровень для отображаемых контуров. Если 0, только один контур. Если 1, этот контур и все контуры на том же самом уровне. Если 2, все контуры одинакового уровня и все контуры на один уровень ниже контуров отображаются, и т.д. Если значение отрицательно, функция рисует только дочерние контуры контура до abs(max_level)-1 уровень.

thickness

Толщина контура.

line_type 

Тип линии (смотрите описание в функции cvLine).

offset

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

 

Функция cvDrawContours рисует контуры в изображении если толщина > =0 или заполняет область, ограниченную контурами если толщина < 0.

Пример использования функции представлен в листинге 8.1.

 

Листинг 8.1.

IplImage* image = cvLoadImage( “image.jpg”, 1 );

 

      //Создаем изображение в градациях серого

      IplImage* img_gray= cvCreateImage( cvSize(image->width,image->height), 8, 1);

 

      CvSeq* contours = 0;   

      CvMemStorage* storage = cvCreateMemStorage(0);

 

      cvCvtColor( image, img_gray, CV_BGR2GRAY );

      cvThreshold( img_gray, img_gray, 128, 255, CV_THRESH_BINARY );

 

      //cvAdaptiveThreshold(img_gray, img_gray, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C ,

      //          CV_THRESH_BINARY, 21, 7);

 

      cvFindContours( img_gray, storage, &contours, sizeof(CvContour),

                    CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

 

      cvDrawContours( image, contours, CV_RGB(255,0,0), CV_RGB(0,255,0),2, 1, CV_AA, cvPoint(0,0) );

 

      cvSaveImage(”img2.jpg”,image );

 

      cvReleaseImage( &image );

 

Результат выделения контуров при использовании функции cvThreshold() представлен на рисунке 8.1, а при использовании «умного» построения монохромного изображения cvAdaptiveThreshold(), представлен на рисунке 8.2.

Рис.8.1. Выделение контуров после приведения изображения к монохромному с помощью функции cvThreshold
Рис.8.1. Выделение контуров после приведения изображения к монохромному с помощью функции cvThreshold
Рис.8.2. Выделение контуров после приведения изображения к монохромному с помощью функции cvAdaptiveThreshold
Рис.8.2. Выделение контуров после приведения изображения к монохромному с помощью функции cvAdaptiveThreshold

 

Для сглаживания и получения более аккуратных контуров можно воспользоваться функцией cvApproxPoly().

 

cvApproxPoly

CvSeq* cvApproxPoly(

const void* src_seq,

int header_size,

CvMemStorage* storage,

int method,

double parameter,

int parameter2=0

);

 

Параметры:

src_seq

Последовательность контуров.

header_size

Размер заголовка аппроксимирующей кривой

storage

Хранилище аппроксимированных контуров.

method

Метод аппроксимации; только CV_POLY_APPROX_DP поддержан, который соответствует алгоритму Дугласа – Пейкера.

parameter

Определенный методом параметр; в случае CV_POLY_APPROX_DP это – желательная точность приближения.

parameter2

Если src_seq – последовательность, это означает, должна ли одиночная последовательность быть аппроксимирована или все последовательности на том же самом уровне или ниже src_seq (см. cvFindContours для описания иерархических структур контура).

 

Функция cvApproxPoly() аппроксимирует одну или большее количество кривых и возвращает результат приближения. Так если в листинг 8.1. ниже функции cvFindContours() вставить следующую строку:

contours = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 );

результат представлен на рисунке 8.3.

Рис.8.3. Выделение контуров после приведения изображения к монохромному с помощью функции cvAdaptiveThreshold и использованию функции cvApproxPoly
Рис.8.3. Выделение контуров после приведения изображения к монохромному с помощью функции cvAdaptiveThreshold и использованию функции cvApproxPoly

 

1. H. Freeman. On the encoding of arbitrary geometric configurations, IRE Transactions on Electronic Computers EC- 10(1961) 260-268.

1 комментарий

  1. Спасибо вам за статью, опробовал на видео – всё в лучшем виде))

    Комментарий от vasist — 4 Январь 2010 @ 11:20 ДП

RSS лента комментариев к этой записи.

Извините, комментирование на данный момент закрыто.

Работает на WordPress