Jump to content
Compvision.ru
Alex_grem

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

Recommended Posts

Да, спасибо, пример хороший.

Только там двумя строчками выше вот какая конструкция:

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

;

//--------------

if(contours!=0)

{

NumCont=contours->total; // количество найденных контуров

}

Если я правильно понимаю тип CvSeq, то в NumCont попадает не общее количество найденных контуров, а количество точек в первом контуре (ну, у меня во всяком случае) - я это имел ввиду.

Андрей.

Если честно, не замечал этого, все работало :blink:, но возможно Вы правы (но я, как нибудь проверю ).

----------------------

Проверил правильно так:

int Nc = cvFindContours(************);

Nc-кол-во найденных контуров.

Share this post


Link to post
Share on other sites

Класс для работы со сплайнами, очень полезно для работы с контурами.

http://willperone.net/Code/spline.php

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Здравствуйте, коллеги,

Есть такая функция cvMatchTemplate. Она работает, но только если темплейт совпадает по положению с изображением:

match.png

Шестерёнки я могу обе найти, а вот моторчик только один. (конечно, в конкретном частном случае могу использовать cvMatchShapes, но бывают случаи когда это невозможно)

Я хочу соорудить аналог cvMatchTemplate, но так, чтобы она была нечувствительна к повороту/масштабу/сдвигу.

Примерно как вот здесь: http://www.lps.usp.br/~hae/software/cirateg/index.html (но там нет исходников)

Хочу вот спросить - может быть кто-нибудь делал подобное, (прежде чем я изобрету велосипед)

Спасибо,

Андрей.

Share this post


Link to post
Share on other sites

Думаю нужно посмотреть в сторону алгоритмов SURF/SIFT, открытые реализации в сети есть, да и в opencv есть функция cvExtractSURF

Share this post


Link to post
Share on other sites

cvMatchTemplate срабатывает и при повороте на 10-15 градусов. Я делал несколько копий с поворотом и прогнял их через cvMatchTemplate. Хуже это с размерами.. При этом надо помнить что могут быть несколько попаданий в один обьект :blink:

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
Господа я в конец замучался.... ни как не получается выделять из контура ни линии ни дуги.....алгоритмов в сети практически нету...точнее я вообще их не нашел,только упоминания о них...может кто нибудь этим занимался?

Вот тут почитайте статейки, про детектирование прямых:

http://www.compvision.ru/forum/index.php?showtopic=31

Непосредственно в этом виде вам он не подходит, но если разберетесь с методом, модифицировать под Вашу задачу труда не составит.

Share this post


Link to post
Share on other sites

У меня пару вопросов по контурам.

1. Как сохранить контуры в файле после их поиска функцией cvFindContours;

2. Как можно сегментировать контуры.

Share this post


Link to post
Share on other sites
У меня пару вопросов по контурам.

1. Как сохранить контуры в файле после их поиска функцией cvFindContours;

2. Как можно сегментировать контуры.

Сохранение контура:

CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE );

cvWrite( fs, "result", result, cvAttrList(0,0) );

cvReleaseFileStorage( &fs );

Считывание контура:

CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_READ );

CvFileNode* fn= cvGetFileNodeByName( fs, cvGetRootFileNode(fs), "result" );

result=(CvSeq*)cvRead( fs, fn );

//-----------------------

// работа с контуром

// - - - - - - - - - - - -

// - - - - - - - - -- - - -

//-----------------------

// освобождение хранилища

cvReleaseFileStorage( &fs );

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

Share this post


Link to post
Share on other sites
Что Вы имеете ввиду под сегментацией контура? Разбить на отрезки (точки), или что то другое ?

Извиняюсь, не уточнил. Я имел ввиду сегментацию формы.

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

Share this post


Link to post
Share on other sites
Извиняюсь, не уточнил. Я имел ввиду сегментацию формы.

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

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

Share this post


Link to post
Share on other sites
Может лучше сегментировать изображение (при помощи cvFloodfill, например получить маски для каждого цветового пятна) а потом определять контуры? Контуры можно конечно распутать, если они обладают свойством гладкости и не имеют разрывов в производных, но это сложный путь, лучше поработать с изображением до выделения контуров.

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

Share this post


Link to post
Share on other sites
Дело в том, что объекты имеют один и тот же цвет. Контуры можно отличить друг от друга функцией cvDilate, но при этом теряется их форма и дальше их уже не распознать. Сейчас я пробую этим методом найти объекты, а их идентифицировать с помощью cvMatchTemplate, но он нечувствителен к повороту.

Насколько я знаю, cvMatchTemplate сохраняет работоспособность при углах поворота плюс-минус 15 градусов, можно делать несколько прогонов. Можно, для сокращения области поиска использовать ROI вычисленную по бинаризованному изображению, которое у Вас уже имеется. Можно попробовать (к бинарному изображению) применить функцию cvDistTransform. Тем самым получите центры объектов. А после этого, по максимальному отклику cvMatchTemplate найти и поворот.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
А можно ли найти наклон произвольного контура с помощью моментов, если известно, что он имеет вытянутую форму по высоте, и большую площадь в верхней части?

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

Вот кусок кода:

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/M_PI);[/code] где xc и yc ищется так:
[code]float xc=(moments.m10/moments.m00);
float yc=(moments.m01/moments.m00);

PS: квадрант может скакать.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
Спасибо, вроде угол наклона правильно считает. Осталось только проблема, что половина изображений вверх ногами получаются. А в примере LL и LW что за величины?

Зто дины осей эллипса (или полуосей, не помню). Насчет переворота - я про квадрант предупреждал :D. Надо доп. обработку какую-то делать.

Share this post


Link to post
Share on other sites
Зто дины осей эллипса (или полуосей, не помню). Насчет переворота - я про квадрант предупреждал :D. Надо доп. обработку какую-то делать.

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

Share this post


Link to post
Share on other sites
Поэкспериментировал, по размерам больше похоже, что длины полуосей. А источник/статью, по которому писали код не можете дать?

OpenCVReferenceManual.pdf страница 2-15 :D

Share this post


Link to post
Share on other sites

здравствуйте! Есть задача: точно и однозначно позиционировать 2 точки на изображении (камера закреплена, а объект перемещается, нужно постоянно знать его относительные координаты). Какой объект лучше всего для этого использовать? В принципе с этой задачей неплохо справляется яркий светодиод, если к камере приложить светофильтр, но все равно периодически появляются лишние точки.

Share this post


Link to post
Share on other sites

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

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

Вот код:

int main(int argc, char** argv)
{
IplImage* src;
const char* main_name = "Workspace";
src = cvCreateImage(cvSize( 400, 400), 8, 3);
cvZero(src);
CvScalar color = CV_RGB( 200,0,0);

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
CvSeqWriter writer;
//CvSeqReader reader;
int i;
cvStartAppendToSeq( seq, &writer );

CvPoint pt = cvPoint(20,20);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(30,50);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(50,60);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(45,30);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
cvEndWriteSeq( &writer );
for (i = 0;i<4;i++)
{
CvPoint* pts = (CvPoint*) cvGetSeqElem(seq, i);
printf("[%d,%d] is read\n", pts->x, pts->y );
}
cvDrawContours( src, seq, color, color,0,3,8);
cvCircle( src, pt, 8, color,1,8,0);

cvNamedWindow( main_name, 1);
cvShowImage( main_name, src);
cvWaitKey(0);
return 0;
}[/codebox]

Share this post


Link to post
Share on other sites
Здравствуйте.

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

Вот код:

int main(int argc, char** argv)
{
IplImage* src;
const char* main_name = "Workspace";
src = cvCreateImage(cvSize( 400, 400), 8, 3);
cvZero(src);
CvScalar color = CV_RGB( 200,0,0);

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
CvSeqWriter writer;
//CvSeqReader reader;
int i;
cvStartAppendToSeq( seq, &writer );

CvPoint pt = cvPoint(20,20);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(30,50);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(50,60);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(45,30);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
cvEndWriteSeq( &writer );
for (i = 0;i<4;i++)
{
CvPoint* pts = (CvPoint*) cvGetSeqElem(seq, i);
printf("[%d,%d] is read\n", pts->x, pts->y );
}
cvDrawContours( src, seq, color, color,0,3,8);
cvCircle( src, pt, 8, color,1,8,0);

cvNamedWindow( main_name, 1);
cvShowImage( main_name, src);
cvWaitKey(0);
return 0;
}[/codebox]

На эту тему, можете посмотреть примеры из opencv/samples/c/convexhull.c и squares.c, там правда для записи элементов используется cvSeqPush.

Share this post


Link to post
Share on other sites

В squares.c вручную рисуют контур, тут проблем нет - считывается из массива все прекрасно. В convexhull.c тоже ничего не нашел. Проблема в том, что cvDrawContours ничего не рисует, и почему так происходит я понять не могу. Думаю, что проблема со списком CvSeq... Но пока ничего поделать с этим не могу. Может с указателем на первый контур что-то не так?

Share this post


Link to post
Share on other sites

я так понял проблема в характеристиках контура. Функция CvMoments с этим контуром вообще пишет ошибку. Не проходит определение

#define CV_IS_SEQ_POLYGON( seq ) \

(CV_IS_SEQ_POLYLINE(seq) && CV_IS_SEQ_CLOSED(seq))

где

#define CV_IS_SEQ_POLYLINE( seq ) \

(CV_SEQ_KIND(seq) == CV_SEQ_KIND_CURVE && CV_IS_SEQ_POINT_SET(seq))

и

#define CV_IS_SEQ_CLOSED( seq ) (((seq)->flags & CV_SEQ_FLAG_CLOSED) != 0)

получается мой контур не полигон) И как его сделать полигоном?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×