OpenCV - найти или получить доступ к контуру формы, не окруженному bg, только разделенному контуром

Я пытался найти контур одной фигуры на очень простом фоне, используя OpenCV findContour (я хотел бы использовать синтаксис C++). Однако он продолжает делать свой контур контуром, а не самой формой. Я думаю, это из-за белого края, полученного из-за Кэнни, который не делает форму закрытой.

Случай A: форма находится у края изображения (это не фактическое входное изображение, а более простое входное изображение, иллюстрирующее эту проблему).

Случай B: Фон окружает фигуру

Вот основные функции, которые я использовал:

findContours( grayImage, contours, hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
approxPolyDP(Mat(contours.at(largestContourIndex)),poly,3,true);
drawContours(output, contours, largestContourIndex, RGB(250,0,100), -1, 8, hierarchy, 0, Point() );

РЕДАКТИРОВАТЬ: Обнаружение пропуска края дает контур, который мне нужен, но мне нужно иметь наилучший приблизительный контур, который я могу получить.

Заранее спасибо.


person leya    schedule 29.03.2012    source источник
comment
Я вижу, вы отредактировали свой пост после моего ответа. Было бы хорошо, если бы вы оставили комментарий к моему ответу, объясняя, помогло ли это, а если нет, то почему подход не работал (т.е. что происходило, когда вы пытались)   -  person penelope    schedule 30.03.2012
comment
Я действительно пробовал ваш подход раньше и несколько других. Я просто не решался сделать этот вопрос сложным и обескураживающим, чтобы ответить. Скоро будут ответы и правки. Спасибо за помощь.   -  person leya    schedule 01.04.2012


Ответы (3)


Пробовали ли вы играться с морфологическими операциями?

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

Я знаю, что в OpenCV есть реализации операций расширения и эрозии, а также операций открытия и закрытия. Очень простой подход, который может сработать в вашей ситуации, — это просто немного стереть форму (может быть, 1-2-3 итерации), а затем делать именно то, что вы уже делаете. Надеюсь, тогда вы получите внешние контуры размытой формы, которые на самом деле должны быть внутренними контурами исходной формы.

Я думаю, что OpenCV на самом деле реализует даже более сложную морфологию, но, как всегда, сначала попробуйте простые вещи: D

person penelope    schedule 29.03.2012
comment
На самом деле я делаю эрозию, а затем расширяю входное изображение и использую трекбары для управления ядрами для каждого из них. Насколько я понимаю, ваш подход позволяет мне устранить части фигуры рядом с ее краями. Но я должен сначала использовать обнаружение краев, прежде чем находить его контуры, чтобы улучшить аппроксимированный контур. Обнаружение краев все равно даст мне черное изображение с контуром. И будет в основном 3 группы пикселей - (1) фон, (2) белый контур и (3) форма, что подводит меня к моей основной проблеме - почему группа № 3 не заключена в контур OpenCV? ТИА - person leya; 01.04.2012

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

Если это не так, попробуйте инвертировать хитрое изображение и повторить процесс.

person dvhamme    schedule 30.03.2012
comment
Это то, что я ожидал, но я попытался построить контуры один за другим и изменить режим контура и методы контура, которые принимаются в качестве параметров findContour OpenCV. Я экспериментировал с моим начальным пороговым значением, но сформированные контуры всегда объединялись вокруг контура. Я попробую ваше предложение. Спасибо. - person leya; 01.04.2012

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

rectangle(input,Point(0,0),Point(input.cols-1,input.rows-1),Scalar(0,0,0),1,8,0);

... следовательно, позволяя Канни нарисовать замкнутый контур формы и давая мне контур формы, который я хочу. Я все еще пытаюсь успешно инвертировать вывод Canny, как предложил @dvhamme, но он все еще дает мне ошибки. Было бы лучше, если бы кто-нибудь указал, как правильно получить или получить доступ к контуру формы, но спасибо всем за помощь.

person leya    schedule 01.04.2012
comment
Я воспроизвел вашу проблему, и инвертирование хитрого изображения не помогает. Что действительно работает, так это использование threshold() для сегментации объекта, а затем запуск findContours(). Детектор контура, по-видимому, на самом деле не предназначен для использования после обнаружения линии, но отлично работает на бинарном сегментированном изображении, независимо от того, касается ли объект края или нет. - person dvhamme; 02.04.2012
comment
Спасибо за ваше время! Я не забуду попробовать threshold(), как только вернусь к этому проекту. Я делал что-то вроде inRange(src_Mat, min, max, dst_Mat) и с тех пор не прикасался к этому. - person leya; 02.04.2012