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

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

Recommended Posts

А на какой строчке падает?

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


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

dps = cvFindDominantPoints( contours, storage_dp, CV_DOMINANT_IPAN, 7, 20, 9, 150 );

через дебаг я не смог зайти.

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


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

Запустил твой пример на одной из твоих картинок. Пишет: "dmax is so big (more than contour diameter) that algorithm could become infinite cycle".

Видимо, его надо выбирать каким-то определённым образом.

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


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

а пишет, то куда? у меня с Unhandled exception at memory location вылетает, в консоли пишет ошибка 392 строчка dominant.cpp

IPPI_CALL( icvFindDominantPointsIPAN( contour, storage, &corners,dmin*dmin, dmax*dmax, dneigh*dneigh, (float)amax ));
пробовал менять параметры и пробовал запускать так же
dps= cvFindDominantPoints( contours, storage_dp, CV_DOMINANT_IPAN);
с дефолтными параметрами судя по коду
int dmin = cvRound(parameter1);

            int dmax = cvRound(parameter2);

            int dneigh = cvRound(parameter3);

            int amax = cvRound(parameter4);

if( amax == 0 )

                amax = 150;

            if( dmin == 0 )

                dmin = 7;

            if( dmax == 0 )

                dmax = dmin + 2;

            if( dneigh == 0 )

                dneigh = dmin;

еще может из-за этого.

Notes:

// User must allocate out_numbers array. If it is small - function fills array

// with part of points and returns error

я так понимаю они там используют, что то типа Detection of High Curvature.

http://visual.ipan.sztaki.hu/corner/node8.html

почему кстати в дебаг может не заходить в функцию?

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


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

У меня заходит - всё компилировал сам.

Текст ошибки - комментарий в файле dominants.cpp из OpenCV, более полный кусок кода:

 error:

/* dmax is so big (more than contour diameter)

that algorithm could become infinite cycle */

cvFree( &sharpness );

cvFree( &distance );

cvFree( &ptInf );

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


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

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

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


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

как сделать границы (после детектора Кенни) более толстыми? например, в 2 раза толще

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


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

Есть результат детектора границ Кенни (как на картинке)

нужно получить кривую(хотя лучше ломаную), огибающую все найденные границы(кроме маленьких). куда копать? (красные линии)

затем нужно выделить прямые линии(ну это я преобразованием хаффа я думаю смогу). (желтая)

поиск начинается с голубого креста.

post-4987-0-68471300-1328350230_thumb.jp

post-4987-0-62639700-1328350237_thumb.jp

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


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

С помощью операции математической морфологии "наращивание".

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


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

нда ребят, не привык думать универский мозг!

задача то тривиальная. из точки проводим 360 прямых(через каждый градус) и находим ближайшую к точке точку пересечения с границами. далее строим ломаную. можно увеличить число прямых в n раз чтобы увеличить точность.

но тем не менее жду еще возможных альтернативных вариантов.

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


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

продолжая всю ту же тему

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

получается как сто странно.

image.png

использую код.

void find_corners(IplImage* img)

{

	IplImage* img_gray = cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);

	cvCvtColor( img, img_gray, CV_BGR2GRAY);

	cvSmooth(img_gray,img_gray,CV_MEDIAN, 3);

	cvThreshold(img_gray, img_gray, 100, 255, CV_THRESH_OTSU);


	vector<vector<Point>> contours;

	cv::findContours((cv::Mat)img_gray,contours,CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


	int K=10;//зависимый параметр от масштаба

	vector<Point> vec;

	for(int i=0;i<contours.size();++i)

	{

		if(contours[i].size()>K)

		{

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

			for(int j=0;j<contours[i].size();++j)

			{

				//считаем расстояние от точки AB и BC

				int a_p=0;

				int c_p=0;

				if (j-K/2<0)

					a_p= contours[i].size()-K/2+j;

				else

					a_p= j-K/2;

				if (j+K/2>=contours[i].size())

					c_p= j+K/2-contours[i].size();

				else

					c_p= j+K/2;


				int a_x= contours[i][a_p].x; 

				int a_y= contours[i][a_p].y;

				int b_x= contours[i][j].x; 

				int b_y= contours[i][j].y;

				int c_x= contours[i][c_p].x; 

				int c_y= contours[i][c_p].y;


				int v1_x= b_x-a_x; 

				int v1_y= b_y-a_y;

				int v2_x= c_x-b_x;

				int v2_y= c_y-b_y;

				double angle= (180/M_PI)*acos((v1_x*v2_x+v1_y*v2_y)/(sqrt((double)(v1_x*v1_x+v1_y*v1_y)*(v2_x*v2_x+v2_y*v2_y))));

				if (angle>70&&angle<110) //пределы изменения угла

					vec.push_back(Point(b_x,b_y));  

			}

		}

	}

	cvZero(img);

	cv::drawContours((cv::Mat)img,contours,-1,CV_RGB(255,0,0));

	for(int i=0;i<vec.size();++i)

	{

		cvDrawCircle( img, vec[i], 1, CV_RGB(0,255,0));

	}

	cvSaveImage("test_dot.png",img);

}

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

может у кого есть идеи?

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


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

вообще наверно надо что то типа спрямления кривой(замена отрезками), но только чтобы были линии только горизонтальные и вертикальные, но у меня не гладкая кривая получается после выделения границ и еще дискретная как бы, нужно ли ее еще дополнительно сглаживать если да так как?

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


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

Может Level-set сегментацию применить сначала? Получим четкую границу с регулируемой степенью гладкости. Затем вычисляем кривизну (curavature) и получаем участки наименьшего радиуса изгиба. Там и будут углы.

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


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

level set если я правильно понимаю это типа active snake, а там наступает морока с параметрами, это раз, а во вторых там обязательно замнкнутые области?

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

и там формулы для параметрически заданной кривой,

я делал так

image.png

для всех точек замкнутого контура, отступал на K точек назад и вперед, и считал угол между этими векторами.

понятно дело что результат сильно зависит от К, а так же от шероховатостей на кривой.

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


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

Ну тогда сплайн (тут я кусок кода выкладывал), затем сплайн регуляризовать, и применять уже этот метод.

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


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

попробовал сделать тупо new_pt[j]=(p1[j-1]+p2[j]+p3[j+1])/3

ну результат стал лучше, но понятное дело не на много.

теоретически надо что то типа Douglas-Peucker-Line-Approx

http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D0%B0%D0%BC%D0%B5%D1%80%D0%B0_%E2%80%94_%D0%94%D1%83%D0%B3%D0%BB%D0%B0%D1%81%D0%B0_%E2%80%94_%D0%9F%D0%B5%D0%BA%D0%B5%D1%80%D0%B0

в opencv это делается похоже approx_poly , но мне надо не совсем то, потому что мне надо сапроксимировать с ограничениями на вертикльность-горизонтальность отрезков , теоретически я вижу решение как найти точки наибольшего изгиба (~90 градусов) и затем между точками сапросимировать кривую отрезком, но на практике мешает волнистость контура.

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

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

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


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

почему то отказывается работать с vector<vector<Point>> vec;

хотя написано

Parameter: points – The input 2D point set, represented by CV_32SC2 or CV_32FC2 matrix, or by vector<Point> or vector<Point2f> converted to the matrix using Mat(const vector<T>&) constructor.

пробовал код

vector<vector<Point>> vec;

Mat t(vec[i]);

cv::Rect rc= cv::boundingRect(t);
и
vector<vector<Point>> vec;

cv::Rect rc= cv::boundingRect(vec[i]);

падает с ошибкой

кстати в approxPolyDP используется тот же самый алгоритм

The functions approxPolyDP approximate a curve or a polygon with another curve/polygon with less vertices, so that the distance between them is less or equal to the specified precision. It used Douglas-Peucker algorithm http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm

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


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

vector<vector<Point>> vec; - здесь в векторе 0 элементов

Mat t(vec); - а здесь пытаемся получить доступ к i-му элементу, вот и ошибка.

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


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

не это я просто написал как я его объявил, понятное дело, что я его заполнил.

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

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

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


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

пытаюсь вписать прямоугольник в контур

Rect FitInRectFigure(vector<Point> vec)

{

//сначала находим точку центра масс

int cx=0;

int cy=0;

for(int i=0;i<vec.size();++i)

{

cx+= vec.x;

cy+= vec.y;

}

cx=cx/vec.size();

cy=cy/vec.size();

//затем начинаем по х и у выращивать рект из центра масс

int x1= cx;

int y1= cy;

int x2= cx;

int y2= cy;

int K=20;

if(vec.size()>K) //отфильтровываем маленькие контуры

{

//Point pt;

Point2f pt;

pt.x= x1;

pt.y= y1;

Mat t(vec);

while(pointPolygonTest(/*vec*/t,pt,false)>0)

{

--x1;

--y1;

pt.x= x1;

pt.y= y1;

}

pt.x= x2;

pt.y= y2;

while(pointPolygonTest(/*vec*/t,pt,false)>0)

{

++x2;

++y2;

Point pt;

pt.x= x2;

pt.y= y2;

}

}

return Rect(x1,y1,x2,y2);

}

почему то в цикле где ++x2;++y2; просходит зацикливание.

причем pointPolygonTest(/*vec*/t,pt,false) при флаге false выдает не +1 -1 0 , а при положительных почему то 100, вообщем такое ощущение что pointPolygonTest то ли неправильно работает, то ли я не правильно его вызываю.

попробовал пример

vector<Point2f> points;


points.push_back(Point2f(0,0));

points.push_back(Point2f(0,4));

points.push_back(Point2f(4,4));

points.push_back(Point2f(4,0));


cout << pointPolygonTest(points, Point2f(5,1), false) << endl;

cout << pointPolygonTest(points, Point2f(1,1), false) << endl;

cout << pointPolygonTest(points, Point2f(0,0), false) << endl;

вывело

-100

100

0

впринципе ответ правильный, но почему сотни непонятно.

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


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

походу старый пустяшный баг (у меня версия 2.3 не из svn) https://code.ros.org/trac/opencv/ticket/1285

но все равно не понятно почему сама функция не работает.

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


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

блин ошибка была в локальной переменной Point pt;

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


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

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

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

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


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

http://www.staff.science.uu.nl/~gerae101/motion_planning/ecm.html

вот нашел еще интересную вещь, но опять же алгоритм алгоритмом(но опять же там не вертикальные\горизонтальные линии), а как получить точки между которыми строить путь? особенно если возможны циклы?

  • Like 1

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×