Перейти к содержимому
Compvision.ru
Alex_grem

Работа с контурами

Recommended Posts

Отлично! Я нашел решение проблемы.

При создании sequence надо делать так:

CvSeq* seq = cvCreateSeq( (CV_SEQ_FLAG_CLOSED|CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_POINT), sizeof(CvContour), sizeof(CvPoint), storage );

Что делает ее полигоном!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
anton    0

Как выделить полученный контур в прямоугольник?

Как вырезать полученный контур в ROI?

НАШЁЛ ОТВЕТ:

CvRect rect = cvBoundingRect(temp);

cvRectangle(img, cvPoint(rect.x, rect.y), cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(0,255,0), 0);

Изменено пользователем anton

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
anton    0

Здравствуйте.

У меня небольшая проблема - создаю контур cvSeq, а потом рисую его с помощью cvDrawContours, но ничего программа не рисует.

Видать проблема в том, что Вы указываете глубину прорисовки равной 0! - попробуйте cvDrawContours( src, seq, color, color,1,3,8); и всё зарисуется!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
anton    0

я вот не могу никак понять, зачем вычислять моменты и прочее, если за похожесть контуров отвечает 1 строка: cvMatchShapes, которая и даёт результат?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
FingerScan    0

По поводу contours->total согласен,это количесвто пикселей в контуре=) просто в мануале написано это это total number of elements,это и вызывает заблуждение=)

Нормально всё в мануале написано :)

Ни про какое "количество пикселей" там не может быть речи, так как у функции поиска контуров есть куча разных методов аппроксимации.

И то что в чьем-то там конкретном случае в контуре оказался именно список пикселей это конечно же классно, но ведь там запросто могла очутиться и запись в цепном коде Фримена, и аппроксимация по Teh-Chin, и сжатые горизонтальные\вертикальные\диагональные доли и т.п.

Так что именно фраза "total number of elements" как нельзя более точно описывает что там на самом деле находится.

А если кто-то хочет позаблуждаться, то он всё равно это сделает, не взирая на то, насколько точно и подробно ему составят мануал :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Есть изображение, на нём я нахожу нужные знаки по заранее сохраненному шаблону (образцу контура), по алгоритму Smorodov'а (огромное спасибо за алгоритм!) .

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

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

Сравнение хочу попробовать матричное (т.е. попиксельное).

Пожалуйста, подскажите, как убрать фон.

P.s. степень "похожести" из примера Smorodov'а умножена у меня на 1000, чтобы не выводить дробную часть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

Привет всем!

подскажите, как правильно найти угол наклона объекта?

хотел использовать поле angle в структуре CvBox2D, но не могу понять как интерпретировать это значение.

в исходниках есть коммент:

/* Angle between the horizontal axis */

/* and the first side (i.e. length) in degrees */

т.е. это угол между горизонтальной осью и первой стороной, но вот какой именно???

буду благодарен за помощь!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Smorodov    523

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

Есть изображение, на нём я нахожу нужные знаки по заранее сохраненному шаблону (образцу контура), по алгоритму Smorodov'а (огромное спасибо за алгоритм!) .

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

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

Сравнение хочу попробовать матричное (т.е. попиксельное).

Пожалуйста, подскажите, как убрать фон.

P.s. степень "похожести" из примера Smorodov'а умножена у меня на 1000, чтобы не выводить дробную часть.

Здесь нужно использовать маску. Рисуем контур (можно все подходящие контуры) (с заливкой) на изображении маски, а затем объединяем с исходным изображением по "И".

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Smorodov    523

Привет всем!

подскажите, как правильно найти угол наклона объекта?

хотел использовать поле angle в структуре CvBox2D, но не могу понять как интерпретировать это значение.

в исходниках есть коммент:

/* Angle between the horizontal axis */

/* and the first side (i.e. length) in degrees */

т.е. это угол между горизонтальной осью и первой стороной, но вот какой именно???

для это изображения:

угол: -80

ширина: 190

высота: 78

а для этого:

угол: -10

ширина: 78

высота: 190

буду благодарен за помощь!!!

На первой странице топика есть код и там такой кусок:

double M00=moments.m00;
double M20=moments.m20;
double M02=moments.m02;
double M11=moments.m11;

double A=(M20/M00)-xc*xc;
double B=2*((M11/M00)-xc*yc);
double C=(M02/M00)-yc*yc;

double LL=sqrt( ( (A+C)+sqrt(B*B+(A-C)*(A-C)) )/2)*2;
double LW=sqrt( ( (A+C)-sqrt(B*B+(A-C)*(A-C)) )/2)*2;

// Для вычисления угла нужны центральные моменты инерции
M20=moments.mu20;
M02=moments.mu02;
M11=moments.mu11;

double theta=(atan2(2*M11,(M02-M20))/2)*(180/pi);[/code]

theta - это угол наклона главной (большей) оси.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Smorodov, большое спасибо!

Вот что у меня вышло:


#include "stdio.h"

#include "cv.h"

#include "highgui.h"


CvArr* temp;

CvSeq* contours = 0; 

CvMemStorage* storage = cvCreateMemStorage(0);


CvSeq* result;

CvSeq* polygons = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );


int main()

{

	IplImage* img1 = 0;

	IplImage* gray = 0;

	IplImage* black = 0;

	IplImage* end = 0;

	IplImage* cann = 0;

	cvNamedWindow("RGB", 1);

	cvNamedWindow("Gray", 1);

	cvNamedWindow("Black", 1);

	cvNamedWindow("End", 1);


	char name0[] = "image2.jpeg";

	img1 = cvLoadImage(name0, 1);

	gray = cvCreateImage( cvSize(img1->width, img1->height), 8, 1);

	black = cvCreateImage( cvSize(img1->width, img1->height), 8, 1);

	end = cvCreateImage( cvSize(img1->width, img1->height), 8, 1);

	cann = cvCreateImage( cvSize(img1->width, img1->height), 8, 1);

	// делаем маску, заливаем изображение чёрным

	cvFillImage(black, 0);


	// переводим основное изображение в серый

  	cvCvtColor( img1, gray, CV_BGR2GRAY);

	// применяем пороговое преобразование

	cvThreshold( gray, cann, 120, 255, CV_THRESH_BINARY );

	// удаляем наружный контур

 	cvRectangle( cann, cvPoint(0,0), cvPoint( cann->width-1, cann->height-1), CV_RGB(0,0,0));

	// утолщаем границы

	cvDilate( cann, cann, 0, 1 );

	// выделяем контура

	cvCanny( cann, cann, 50, 150, 5 );

	// находим контура

	cvFindContours( cann, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

	// рисуем найденный контур НА маске и заливаем его белым (атрибут CV_FILLED)

	cvDrawContours( black, contours, CV_RGB(255,255,255),CV_RGB(255,255,255), 0, CV_FILLED, CV_AA, cvPoint(0,0));

	// сравниваем логическим "и",

	cvAnd(gray, black, end);

	// рисуем контур на исходном изображени, чтобы не мешал при сравнении

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


	cvShowImage("RGB", img1);

	cvShowImage("Gray", gray);

	cvShowImage("Black", black);

	cvShowImage("End", end);


		char c = cvWaitKey();


	cvDestroyWindow( "RGB" );

	cvDestroyWindow( "Gray" );

    cvDestroyWindow( "Black" );

	cvDestroyWindow( "End" );

	cvReleaseImage(&img1);


  return 0;

}

Естественно, это работает, если на исходном изображении нужный контур - первый. Иначе сам контур нужно задавать явно.

Собственно, именно это мне и нужно было. Теперь буду думать как сравнить знак с эталоном.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

Smorodov, спасибо что откликнулись!

а у меня новая проблема :(

есть изображение:

нужно получить контур этой микросхемы

так как некоторые лапки не связаны с остальными, то я нахожу все контуры, добавляю их точки в одну последовательность, а потом нахожу ConvexHull, таким образом получаю один контур вокруг всех лапок => и вокруг микросхемы, НО... на этом изображении в правом верхнем углу есть блик.

в бинарном виде она выглядит так:

post-1-0-73161700-1301772265_thumb.jpg

этот блик (а в общем любой шум за пределами нужного мне контура) так же расценивается как объект и естественно его точки добавляются в общий контур и все не правильно :(

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Smorodov    523

Если микросхема всегда выровнена, то можно попробовать находить суммы по столбцам и строкам. Максимумы этих сумм покажут габариты микросхемы. см. функцию cvReduce (описание)

Пример использования функции : http://www.compvision.ru/wiki/%D0%9F%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BB%D0%B8%D1%86%D0%B0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

Если микросхема всегда выровнена, то можно попробовать находить суммы по столбцам и строкам. Максимумы этих сумм покажут габариты микросхемы. см. функцию cvReduce (описание)

Пример использования функции : http://www.compvision.ru/wiki/%D0%9F%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BB%D0%B8%D1%86%D0%B0

спасибо, посмотрю, но микросхема может быть смещена от центра и быть под углом к горизонтали, мне-то как раз и нужно определить это смещение и угол :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Smorodov    523

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

Эффекта слияния ножек в одну линию можно достичь так-же парой функций cvDilate+cvErode, а затем искать квадраты или линии.

post-1-0-50863400-1301772107_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

посмотрел cvReduce... т.е. если взять бинарное изображение из предыдущего поста и найти сумму по столбцам и строкам, то максимумы приблизительно будут указывать на границы микросхемы, правильно я понимаю? но это если она будет выровнена, как Вы говорили...

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

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

а можно поподробнее? что значит

прогнать через стандартный пример squares

Эффекта слияния ножек в одну линию можно достичь так-же парой функций cvDilate+cvErode, а затем искать квадраты или линии.

хм, cvDilate пробовал, а вот про последующий cvErode не подумал, спасибо...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Smorodov    523

В директории opencv2.2/Bin/ (у меня) лежит пример squares.exe он открывает картинки pic1.png - pic6.png и ищет на них прямоугольники (или квадраты). См. картинку выше.

Исходник squares лежит в директории c:\OpenCV-2.2.0\samples\cpp\

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
maximator    1

В директории opencv2.2/Bin/ (у меня) лежит пример squares.exe он открывает картинки pic1.png - pic6.png и ищет на них прямоугольники (или квадраты). См. картинку выше.

Исходник squares лежит в директории c:\OpenCV-2.2.0\samples\cpp\

ага, нашел, спасибо, буду изучать...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
zaza    0

Здравствуйте! У меня не получается выцепить последовательность координат, по которым строится внутренний контур объекта при использовании cvFindContours. Посоветуйте что-нибудь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    202

Выкладывай свой код, поможем конечно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
zaza    0

уже разобралась)) спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
zaza    0

Здравствуйте! Возник вопрос - как можно проверить находится ли точка внутри контура или нет ? контур нахожу при помощи cvFindContours. Т.е. мне известны координаты точек, по которым строится контур, и есть еще набор точек. мне нужны только те, что внутри контура.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    202

Если точек для проверки много, то можно поступить следующим образом: закрасить лежащую снаружи контура область изображения одним цветом, нарисовать контур другим, а внутренность контура - третьим. И просто брать значение пикселя по координатам точек. То есть:

1. Создать одноканальное изображение размеров с исходное, закрасить его нулями (cvSet).

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

3. Нарисовать контур цветом, скажем, 128.

4. В точке bounding_rect.x + 1 и bounding_rect.y + 1 вызвать функцию cvFloodFill с белым цветом.

5. Для каждой интересующей точки проверить значение пикселя.

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

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
zaza    0

а зачем мне прямоугольник описывающий для контура?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    202

Чтобы не закрашивать всё изображение. Он не обязателен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×