Smorodov 572 Report post Posted June 11, 2010 Да, спасибо, пример хороший. Только там двумя строчками выше вот какая конструкция: cvFindContours( gray, storage,&contours,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0)) ; //-------------- if(contours!=0) { NumCont=contours->total; // количество найденных контуров } Если я правильно понимаю тип CvSeq, то в NumCont попадает не общее количество найденных контуров, а количество точек в первом контуре (ну, у меня во всяком случае) - я это имел ввиду. Андрей. Если честно, не замечал этого, все работало , но возможно Вы правы (но я, как нибудь проверю ). ---------------------- Проверил правильно так: int Nc = cvFindContours(************); Nc-кол-во найденных контуров. Share this post Link to post Share on other sites
Smorodov 572 Report post Posted June 12, 2010 Класс для работы со сплайнами, очень полезно для работы с контурами. http://willperone.net/Code/spline.php Share this post Link to post Share on other sites
Новатор 0 Report post Posted June 12, 2010 По поводу contours->total согласен,это количесвто пикселей в контуре=) просто в мануале написано это это total number of elements,это и вызывает заблуждение=) Share this post Link to post Share on other sites
AndreyDmitriev 0 Report post Posted June 13, 2010 Здравствуйте, коллеги, Есть такая функция cvMatchTemplate. Она работает, но только если темплейт совпадает по положению с изображением: Шестерёнки я могу обе найти, а вот моторчик только один. (конечно, в конкретном частном случае могу использовать cvMatchShapes, но бывают случаи когда это невозможно) Я хочу соорудить аналог cvMatchTemplate, но так, чтобы она была нечувствительна к повороту/масштабу/сдвигу. Примерно как вот здесь: http://www.lps.usp.br/~hae/software/cirateg/index.html (но там нет исходников) Хочу вот спросить - может быть кто-нибудь делал подобное, (прежде чем я изобрету велосипед) Спасибо, Андрей. Share this post Link to post Share on other sites
quosego 5 Report post Posted June 13, 2010 Думаю нужно посмотреть в сторону алгоритмов SURF/SIFT, открытые реализации в сети есть, да и в opencv есть функция cvExtractSURF Share this post Link to post Share on other sites
wowa 0 Report post Posted June 14, 2010 cvMatchTemplate срабатывает и при повороте на 10-15 градусов. Я делал несколько копий с поворотом и прогнял их через cvMatchTemplate. Хуже это с размерами.. При этом надо помнить что могут быть несколько попаданий в один обьект Share this post Link to post Share on other sites
Новатор 0 Report post Posted June 19, 2010 Господа я в конец замучался.... ни как не получается выделять из контура ни линии ни дуги.....алгоритмов в сети практически нету...точнее я вообще их не нашел,только упоминания о них...может кто нибудь этим занимался? Share this post Link to post Share on other sites
Smorodov 572 Report post Posted June 20, 2010 Господа я в конец замучался.... ни как не получается выделять из контура ни линии ни дуги.....алгоритмов в сети практически нету...точнее я вообще их не нашел,только упоминания о них...может кто нибудь этим занимался? Вот тут почитайте статейки, про детектирование прямых: http://www.compvision.ru/forum/index.php?showtopic=31 Непосредственно в этом виде вам он не подходит, но если разберетесь с методом, модифицировать под Вашу задачу труда не составит. Share this post Link to post Share on other sites
anry 0 Report post Posted July 27, 2010 У меня пару вопросов по контурам. 1. Как сохранить контуры в файле после их поиска функцией cvFindContours; 2. Как можно сегментировать контуры. Share this post Link to post Share on other sites
Smorodov 572 Report post Posted July 27, 2010 У меня пару вопросов по контурам. 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
anry 0 Report post Posted July 28, 2010 Что Вы имеете ввиду под сегментацией контура? Разбить на отрезки (точки), или что то другое ? Извиняюсь, не уточнил. Я имел ввиду сегментацию формы. Нужно аппроксимированный контур сегментировать по точкам перегиба, чтобы получить не один контур, а два и более. Мне это нужно чтобы "расклеить" слипшиеся объекты. Share this post Link to post Share on other sites
Smorodov 572 Report post Posted July 28, 2010 Извиняюсь, не уточнил. Я имел ввиду сегментацию формы. Нужно аппроксимированный контур сегментировать по точкам перегиба, чтобы получить не один контур, а два и более. Мне это нужно чтобы "расклеить" слипшиеся объекты. Может лучше сегментировать изображение (при помощи cvFloodfill, например получить маски для каждого цветового пятна) а потом определять контуры? Контуры можно конечно распутать, если они обладают свойством гладкости и не имеют разрывов в производных, но это сложный путь, лучше поработать с изображением до выделения контуров. Share this post Link to post Share on other sites
anry 0 Report post Posted July 28, 2010 Может лучше сегментировать изображение (при помощи cvFloodfill, например получить маски для каждого цветового пятна) а потом определять контуры? Контуры можно конечно распутать, если они обладают свойством гладкости и не имеют разрывов в производных, но это сложный путь, лучше поработать с изображением до выделения контуров. Дело в том, что объекты имеют один и тот же цвет. Контуры можно отличить друг от друга функцией cvDilate, но при этом теряется их форма и дальше их уже не распознать. Сейчас я пробую этим методом найти объекты, а их идентифицировать с помощью cvMatchTemplate, но он нечувствителен к повороту. Share this post Link to post Share on other sites
Smorodov 572 Report post Posted July 28, 2010 Дело в том, что объекты имеют один и тот же цвет. Контуры можно отличить друг от друга функцией cvDilate, но при этом теряется их форма и дальше их уже не распознать. Сейчас я пробую этим методом найти объекты, а их идентифицировать с помощью cvMatchTemplate, но он нечувствителен к повороту. Насколько я знаю, cvMatchTemplate сохраняет работоспособность при углах поворота плюс-минус 15 градусов, можно делать несколько прогонов. Можно, для сокращения области поиска использовать ROI вычисленную по бинаризованному изображению, которое у Вас уже имеется. Можно попробовать (к бинарному изображению) применить функцию cvDistTransform. Тем самым получите центры объектов. А после этого, по максимальному отклику cvMatchTemplate найти и поворот. Share this post Link to post Share on other sites
anry 0 Report post Posted August 12, 2010 А можно ли найти наклон произвольного контура с помощью моментов, если известно, что он имеет вытянутую форму по высоте, и большую площадь в верхней части? Share this post Link to post Share on other sites
Smorodov 572 Report post Posted August 12, 2010 А можно ли найти наклон произвольного контура с помощью моментов, если известно, что он имеет вытянутую форму по высоте, и большую площадь в верхней части? Если вычислить моменты можно найти главные оси , зная главные оси находим наклон (если требуемая ось повернута и (или смещена), измеряем смещение (линейное или угловое) и корректируем). Вот кусок кода: 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
anry 0 Report post Posted August 20, 2010 Спасибо, вроде угол наклона правильно считает. Осталось только проблема, что половина изображений вверх ногами получаются. А в примере LL и LW что за величины? Share this post Link to post Share on other sites
Smorodov 572 Report post Posted August 20, 2010 Спасибо, вроде угол наклона правильно считает. Осталось только проблема, что половина изображений вверх ногами получаются. А в примере LL и LW что за величины? Зто дины осей эллипса (или полуосей, не помню). Насчет переворота - я про квадрант предупреждал . Надо доп. обработку какую-то делать. Share this post Link to post Share on other sites
anry 0 Report post Posted August 22, 2010 Зто дины осей эллипса (или полуосей, не помню). Насчет переворота - я про квадрант предупреждал . Надо доп. обработку какую-то делать. Поэкспериментировал, по размерам больше похоже, что длины полуосей. А источник/статью, по которому писали код не можете дать? Share this post Link to post Share on other sites
Smorodov 572 Report post Posted August 22, 2010 Поэкспериментировал, по размерам больше похоже, что длины полуосей. А источник/статью, по которому писали код не можете дать? OpenCVReferenceManual.pdf страница 2-15 Share this post Link to post Share on other sites
RuZ 0 Report post Posted October 7, 2010 здравствуйте! Есть задача: точно и однозначно позиционировать 2 точки на изображении (камера закреплена, а объект перемещается, нужно постоянно знать его относительные координаты). Какой объект лучше всего для этого использовать? В принципе с этой задачей неплохо справляется яркий светодиод, если к камере приложить светофильтр, но все равно периодически появляются лишние точки. Share this post Link to post Share on other sites
artemopolus31 0 Report post Posted October 18, 2010 Здравствуйте. У меня небольшая проблема - создаю контур 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
Smorodov 572 Report post Posted October 18, 2010 Здравствуйте. У меня небольшая проблема - создаю контур 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
artemopolus31 0 Report post Posted October 18, 2010 В squares.c вручную рисуют контур, тут проблем нет - считывается из массива все прекрасно. В convexhull.c тоже ничего не нашел. Проблема в том, что cvDrawContours ничего не рисует, и почему так происходит я понять не могу. Думаю, что проблема со списком CvSeq... Но пока ничего поделать с этим не могу. Может с указателем на первый контур что-то не так? Share this post Link to post Share on other sites
artemopolus31 0 Report post Posted October 18, 2010 я так понял проблема в характеристиках контура. Функция 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