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

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

Recommended Posts

кто нибудь сталкивался с такой неприятной особенностью, что рамка толщиной в 1 пиксель не определяется как один объект?

может это возможно как то решить?

+много мелких контуров находит.

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


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

Ну, самый очевидный вариант - cvDilate. Он тебе подойдёт?

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


Ссылка на сообщение
Поделиться на других сайтах
Ну, самый очевидный вариант - cvDilate.

ну да так вроде работает.

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


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

как к cvSeq содержащему контуры добавить cvSeq?

и как узнать кол-во конутров в cvSeq? непонятно, что показывает ->total кол-во контуров или кол-во точек из которых состоят контуры.

и опять же например int Nc= cvFindContours(..) Nc - это кол-во найденных контуров?

void GetALLContour(IplImage* img)

{

	CvMemStorage* image_storage = cvCreateMemStorage(0);

	CvMemStorage* all_contour_storage = cvCreateMemStorage(0);

	CvSeq* all_contours= cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), all_contour_storage);

	CvSeq* temp_contours;


	for (int i=0;i<256;i=i+10)

	{

		for (int j=0;j<256;j=j+10)

		{

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

			cvCvtColor( img, img_gray, CV_BGR2GRAY);


			cvDilate( img_gray, img_gray, 0, 1 );

			cvCanny(img_gray, img_gray, i, j, 3);


			int Nc= cvFindContours(img_gray, image_storage, &temp_contours, sizeof(CvContour), CV_RETR_TREE);

			cvReleaseImage( &img_gray );


			while(temp_contours)

			{

			     cvSeqPush(all_contours,temp_contours);   // тут видимо не правильно

			     temp_contours=temp_contours->h_next;

			}

		}

	}


	while(all_contours)

	{

		cvDrawContours( img, all_contours, CV_RGB(255,0,0), CV_RGB(0,255,0), 0, 0, CV_AA, cvPoint(0,0) );

		//CvRect rect = cvBoundingRect(all_contours);

		//printf("%d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);


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


		all_contours = all_contours ->h_next;

		cvNamedWindow( "Window1", 0 );

		cvShowImage( "Window1", img );

		cvWaitKey(0);

	}


	cvDestroyWindow( "Window1" );

	cvClearMemStorage( image_storage );

} 

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


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

У меня контуры почему то всё равно представляются тем маленьким кружочком не знаю что не так и книжку "Learning OpenCV" о контурах про использование флагов читал не понятно где ошибаюсь вывод контуров тот же


// Объявление читалки точек

CvSeqReader reader;

// Инициализация читалки точек

cvStartReadSeq( contour, &reader, 0 );

// Две точки

CvPoint pt[2];


for( int i=0; i<contour->total-1; i++ )

{

        CV_READ_SEQ_ELEM( pt[0], reader );

        CV_READ_SEQ_ELEM( pt[1], reader );

        cvLine(img12,pt[0],pt[1],CV_RGB(255,0,0),4);

}

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

Раз работает, то первоначальная проблема: разные рантаймы OpenCV и твоего приложения (то есть CRT - C run time).

а как сделать ну что бы они совпадали что бы можно было полностью интерфейсом С++ пользоваться

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


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

У меня контуры почему то всё равно представляются тем маленьким кружочком не знаю что не так и книжку "Learning OpenCV" о контурах про использование флагов читал не понятно где ошибаюсь вывод контуров тот же

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

IplImage* src = cvLoadImage( "d:/video_bmp/1_1.jpg", CV_LOAD_IMAGE_GRAYSCALE );

    IplImage* src1= cvCreateImage( cvGetSize(src), 8, 1 );


	cvThreshold(src,src1,110,255,CV_THRESH_BINARY);

	cvNamedWindow( "Source", 1 );

	cvShowImage( "Source", src1 );


	IplImage* img12 = cvCreateImage( cvGetSize(src), 8, 3 );

	cvSet(img12, cvScalar(0, 0, 0));


	CvMemStorage *storage = cvCreateMemStorage(0);

	CvContourScanner cscaner = cvStartFindContours(src1, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


	for (CvSeq *contour = cvFindNextContour(cscaner); contour; contour = cvFindNextContour(cscaner))

	{

		CvSeqReader reader;

		cvStartReadSeq( contour, &reader, 0 );


		CvPoint pt[2];

		for (int i = 0; i < contour->total - 1; i += 2)

		{

			CV_READ_SEQ_ELEM(pt[0], reader);

			CV_READ_SEQ_ELEM(pt[1], reader);

			cvLine(img12, pt[0], pt[1], CV_RGB(255, 0, 0), 4);

		}

	}


	cvEndFindContours(&cscaner);

	cvReleaseMemStorage(&storage);



	cvShowImage( "img12", img12 );


	cvReleaseImage(&img12);

	cvReleaseImage(&src1);

	cvReleaseImage(&src);


	cvWaitKey(0);

а как сделать ну что бы они совпадали что бы можно было полностью интерфейсом С++ пользоваться

Я же в самом начале написал - одинаково компилировать.

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


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

Большое спасибо с вашим примером разобрался полностью

теперь пытаюсь полностью на с++ сделать

Я же в самом начале написал - одинаково компилировать.

я использую Visual Studio 2008 opencv 2.2

на студии создаю проект Консольное приложение Win32 ну а потом присоединяю opencv к проекту и компилирую я думал что он должен бы с++ компилятор использовать

название приложения name.cpp я что-то не знаю где ещё что поменять что бы использовать другой(c++) компилятор

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


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

С и С++ имеется ввиду стиль написания программы, а не компилятор.

Компилятор VS использует C++ ный если расширение cpp.

C++ интерфейс:

cv::Mat img;
capture>>img;
std::cout<<"hello world";
cv::imshow("win",img);[/code] C интерфейс:
[code]IplImage* img;
img=cvQueryFrame( capture );
printf("hello world");
cvShowImage("win",img);

  • Like 1

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


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

я использую Visual Studio 2008 opencv 2.2

на студии создаю проект Консольное приложение Win32 ну а потом присоединяю opencv к проекту и компилирую я думал что он должен бы с++ компилятор использовать

название приложения name.cpp я что-то не знаю где ещё что поменять что бы использовать другой(c++) компилятор

Ты в режиме компиляции Debug подключаешь Debug версию OpenCV? А в режиме Release - Release OpenCV?

1. Дело в том, что, например, sizeof(std::vector) в Debug не равен sizeof(std::vector) в Release. Поэтому, если программа и OpenCV скомпилирована по-разному, то при передаче того же std::vector будет ошибка.

2. Ещё один момент: чтобы выделять память в dll, а освобождать её в exe надо использовать один и тот же менеджер памяти. А, значит, надо компилировать и exe и dll из OpenCV с опцией "Multithread debug dll" в Debug режиме и "Multithread dll" в Release.

Почему это важно? Ты передаёшь в функцию поиска контуров пустой std::vector, ожидаешь, что его заполнят точками. То есть при передаче вектора как параметра должно соблюдаться правило (1), а именно sizeof(std::vector) из exe должен быть равен sizeof(std::vector) из dll. Далее вектор заполняется точками, то есть происходит выделение памяти под них внутри dll. А освобождаться эта память будет уже в деструкторе вектора в exe. То есть должно соблюдаться правило (2). Иначе получишь ошибку освобождения памяти - твоя программа упадёт при выходе из функции.

Всё это может быть для тебя не очевидно, да и в учебниках, как правило, не разъясняется. Но по-другому нельзя.

  • Like 1

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


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

Ребят, чего-то я затупил:

Чем отличаются CvMoments от CvHuMoments?

typedef struct CvMoments

{

    double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; /* spatial moments */

    double  mu20, mu11, mu02, mu30, mu21, mu12, mu03; /* central moments */

    double  inv_sqrt_m00; /* m00 != 0 ? 1/sqrt(m00) : 0 */

}

CvMoments;


/* Hu invariants */

typedef struct CvHuMoments

{

    double hu1, hu2, hu3, hu4, hu5, hu6, hu7; /* Hu invariants */

}

CvHuMoments;

что это за 7 параметров double hu1, hu2, hu3, hu4, hu5, hu6, hu7; и для чего нужны?

Не найдется ли у кого ссылки на материал по этим алгоритмам? Хотелось бы просвятится по этой теме.

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


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

Image Moment.

И еще небольшая статейка.

О моментах контура.pdf

Моменты Ху это своеобразный "отпечаток пальца" для контура.

Этот набор чисел не меняется при переносе, повороте и масштабировании.

А обычные моменты это удобные характеристики контуров, например нулевой момент - это площадь фигуры. Первые моменты - это что-то вроде линейной плотности вдоль заданной оси.

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

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


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

непонятно как соответсвуют момент из статьи О моментах контура.pdf моментам Ху которые вычисляются в опенцв?

UPD: понятно

M20=moments.mu20;

M02=moments.mu02;

M11=moments.mu11;

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


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

Всем привет.

Возникла такая задача:

У меня есть массив с точками контура, при этом эти точки находятся в произвольном порядке в массиве. Необходимо отсортировать эти точки так, чтобы они шли друг за другом, описывая контур.

В OpenCV есть методы, которые позволяют это сделать быстро ?

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


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

Если контур выпуклый, то cvConvexHull даст нужный эффект, если нет, то все сложнее. А связи точек заданы?

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


Ссылка на сообщение
Поделиться на других сайтах
Если контур выпуклый, то cvConvexHull даст нужный эффект, если нет, то все сложнее. А связи точек заданы?

Нет. В массиве просто хранятся точки в произвольном порядке.

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

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


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

Даже на небольшом наборе точек можно построить очень большое количество контуров (см. хотя-бы http://en.wikipedia.org/wiki/Travelling_salesman_problem). Нужны хотя-бы какие-то критерии определения соседних точек.

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


Ссылка на сообщение
Поделиться на других сайтах
Даже на небольшом наборе точек можно построить очень большое количество контуров (см. хотя-бы http://en.wikipedia....alesman_problem). Нужны хотя-бы какие-то критерии определения соседних точек.

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

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


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

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

ЗЫ: Еще для подобных задач применяют LevelSet метод.

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


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

Спасибо. Действительно оказалось проще отрисовать область монотонным цветом и найти её контур стандартным способом.

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


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

Поставлена интересная задача:

У меня на изображении около 50 окружностей (несколько идеальных окружностей и множество окружностей с искаженной формой-обкусанные, сжатые).

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

Скажите возможно ли щелчком мыши по изображению в области эталона как-то тем самым обозначить этот эталон, чтобы при вычислении моментов он имел значение равное нулю, а все остальные объекты на изображении с ним сравнивались?

Либо есть способ легче?

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


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

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

можно искать окружности через преобразование хафа.

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


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

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

можно искать окружности через преобразование хафа.

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

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

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


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

Если внимательно почитать про моменты Ху, то там говорится, что эти моменты не чуствительны к масштабу и повороту.

Из этого следует, что моменты Ху для окружности можно посчитать только один раз. И сравнивать дальше с ними.

Что касается Хафа, то он не чувствителен к разрывам контура, диапазон значений радиусов, да, лучше знать. Но можно контуры отсеивать по значению периметра.

Выделение эталона мышкой тоже не сложно сделать. Щелкаем мышью, запоминаем точку и находим окружность с центром наиболее близким к этой точке.

Или выделить окошком ROI найти там самую большую окружность, это и будет эталон. Затем сбросить ROI и проводить сравнение дальше.

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


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

Если внимательно почитать про моменты Ху, то там говорится, что эти моменты не чуствительны к масштабу и повороту.

Из этого следует, что моменты Ху для окружности можно посчитать только один раз. И сравнивать дальше с ними.

Что касается Хафа, то он не чувствителен к разрывам контура, диапазон значений радиусов, да, лучше знать. Но можно контуры отсеивать по значению периметра.

Выделение эталона мышкой тоже не сложно сделать. Щелкаем мышью, запоминаем точку и находим окружность с центром наиболее близким к этой точке.

Или выделить окошком ROI найти там самую большую окружность, это и будет эталон. Затем сбросить ROI и проводить сравнение дальше.

Спасибо, попробую.

И еще один очень важный для меня вопрос: Допустим нашлись все контуры на изображении. Каким образом можно сделать так, чтобы в отдельном окне появлялась нарезка (галерея) найденных контуров/объектов?

То есть, обведенный контуром объект копировался без фона и вырисовывался в отдельном окне, и каждый следующий объект копировался и вырисовывался в это же окно следом за предыдущим?

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×