Вы находитесь на странице: 1из 20

с/к Анализ изображений, OpenCV

6. Выделение контуров

http://howto.nicubunu.ro/gears/gears_16.png

лекции и объявления: вопросы отправляйте на адрес УрГУ / ИММ осень 2010


www.uralvision.blogspot.com perevalovds@gmail.com
Понятие контура
Понятие контура
Контур объекта - это линия, представляющая край формы объекта.

Если имеется разбиение изображения на области, соответствующие разным


объектам, то их внешние контуры можно указать однозначно.

Для указания внутренних контуров нужна 3d модель объекта. В этом случае


контурами будут проекции на изображение линий изгиба 3d объекта.

http://cvpr.uni-muenster.de/research/rack/index.html
Понятие контура
Если дано изображение, на котором надо выделить контуры,
но нет ни разбиения на области, ни 3d-модели,
то возникают неоднозначности определения, что такое контур,

связанные с
- масштабом (насколько мелкие интересуют объекты)
- текстурой (являются ли элементы текстуры контурами)
- семантикой (иногда линии на изображении являются просто нарисованными на
объекте, и не отражают изгибов его формы)

Считать ли куст объектом, и искать только его контур,


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

Контур на изображении - это линия, вдоль которой наблюдается скачок по яркости или
цвету.

Контуров на изображении больше, чем контуров объектов на этом изображении.


Поэтому после решения задачи поиска контуров на изображении производится их
дополнительный анализ с целью выявления интересующих контуров объектов.
Зачем нужно находить контур
1. Распознавание

Контур объекта обычно хорошо характеризует его форму.


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

2. Проведение измерений

С помощью контура можно точно оценить размеры


объекта, их поворот и расположение - важно для для
автоматизации промышленности, робототехники,
интерактивных систем.
Поиск точек контура
Фильтр Собела

Для подчеркивания точек контуров чаще всего применяют фильтр Собела.

void Sobel(const Mat& src, //входное изображение


Mat& dst, //выходное изображение, размер и каналов - как у src
int ddepth, //глубина результата, например, CV_32F
int xorder, //порядок производной по x
int yorder, //порядок производной по y
int ksize=3, //размер окна: 1, 3, 5, 7
double scale=1, double delta=0, //масштабирование и сдвиг результата
int borderType=BORDER_DEFAULT) //работа с границей
Фильтр осуществляет Гауссово сглаживание и взятие частных производных 1, 2, 3 порядка
или смешанных ( xorder по x, yorder по y).
(Гауссово сглаживание позволяет получить результат, устойчивый к шумам на
изображении.)
Фильтр Собела
Пример
Mat image = imread( "lodka.jpg" ); //Загрузить изображение с диска
imshow( "image", image ); //Показать изображение
Mat imageDX, imageDY;
Sobel( image, imageDX, CV_32F, 1, 0, 3, 1.0 / 255.0 ); //производная по x
Sobel( image, imageDY, CV_32F, 0, 1, 3, 1.0 / 255.0 ); //производная по y

Обратите внимание, что показаны только положительные значения. Отрицательные и


нулевые значения - показаны черным цветом.
Фильтр Собела
Пример, продолжение

Если трансформировать картинки в серый цвет


и взять sqrt( imageDX^2 + imageDY^2 ) - получим подчеркивание точек контура.
Применив к ним пороговую обработку, получим набор точек контура.

Mat grayX, grayY;


cvtColor( imageDX, grayX, CV_RGB2GRAY );
cvtColor( imageDY, grayY, CV_RGB2GRAY );
pow(grayX, 2, grayX);
pow(grayY, 2, grayY);

Mat contImg = grayX + grayY;


sqrt(contImg, contImg);
contImg.convertTo( temp, CV_8UC3, 255.0 );

Mat binary;
threshold( contImg, binary, 0.7, 1.0, CV_THRESH_BINARY );
Фильтр Собела
Пример, продолжение
Другие фильтры подчеркивания
точек контура
1. Scharr() ,
2. Laplacian(),
3. разность двух Гауссианов (см. в лекции про сглаживание).

Все они работают по принципу, аналогичному методу Собела.

У всех рассмотренных методов такой недостаток: они работают на уровне


отдельных пикселов, а потому получаемые контуры не являются непрерывными
гладкими линиями.

Решение: использовать алгоритм Канни.


Детектор краев Канни

Является многоэтапным алгоритмом, включающим в себя


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

Использует метод двух порогов.

Идея - трассировать контур, двигаясь вдоль точек с


максимальным значением "контура".

На выходе алгоритм дает бинарную картинку с найденными


пикселами, соответствующими контурам.
Детектор краев Канни
void Canny( const Mat& image, //входное изображение, 1-канальное, 8-битное
Mat& edges, //выходное изображение
double threshold1, //пороги, наибольший - для зародышей контура,
double threshold2, //наименьший - для склейки контуров
int apertureSize=3, //окно для фильтра Собела
bool L2gradient=false //использовать ли евклидову длину вектора
//производных Собела, sqrt( dx*dx + dy * dy),
//или просто |dx| + |dy|
);
Детектор краев Канни
Пример
Mat imageGray, edges;
cvtColor( image, imageGray, CV_RGB2GRAY );
Canny( imageGray, edges, 230, 150 );

Исходная картинка Собел + пороговая обработка Детектор краев Канни


Векторизация контуров
Трассировка контура

Трассировка контура - это построение по набору пикселов


ломаной, т.е. построение векторного представления
контура.

Векторное представление удобно с точки зрения


последующей обработки и анализа контура:

- сглаживание и прореживание.
- модификация (поворот, растяжение).
- сопоставление, анализ и распознавание объектов по их
контурам.
Трассировка контуров
void findContours(const Mat& image, //Входное изображение,
//1-канальное, 8-битное
//трактуется как бинарное (0 и не 0)
vector<vector<Point> >& contours, //Найденные контуры
int mode, //Режим поиска контуров
int method, //Способ аппроксимации контуров
Point offset=Point() //Сдвиг всех результрующих контуров
)

Значения mode:
CV_RETR_EXTERNAL - только внешние контуры,
CV_RETR_LIST - список всех контуров
Используется другая форма функции, см. документацию:
CV_RETR_CCOMP - 2-уровневая иерархия - внешние границы и границы дырок,
CV_RETR_TREE - стоит дерево вложенных контуров,

Значения method:
CV_CHAIN_APPROX_NONE - без аппроксимации
CV_CHAIN_APPROX_SIMPLE - выбрасявает горизонтальные и вертикальные точки внутри отрезков
CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS - аппроксимация методом Teh-Chin
Трассировка контуров
Пример
vector<vector<Point> > contours;
findContours( edges, contours, CV_RETR_LIST, CV_CHAIN_APPROX_TC89_L1 );

Mat draw = image.clone();


drawContours( draw, contours, -1, Scalar( 255, 0, 0 ) );
imshow( "find cont", draw );
Анализ контуров

Для определения того, какому объекту принадлежит контур, используют


геометрические характеристики
- длина контура,
- площадь области, огороженной контуром,
- распределение кривизны вдоль контура,

Также, статистические моменты и преобразование Фурье и алгоритмы


прямого сопоставления контуров.

Проблемы

- если объект существенно трехмерный, то его внешний контур может


сильно меняться при вращении объекта.
- если объект загорожен другим объектом, это добавляет сложности к
алгоритму распознавания.

Оценить