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

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

Recommended Posts

Есть контура в них прямоугольники и еще сбоку сверху или еще где-то прилипший другой контур, причем не факт что там вообще есть прямоугольник. Как проверить есть ли там прямоугольник и выделить его? условия на все дело не больше 3-5мс

post-5717-0-70198500-1366062139_thumb.pn

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


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

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

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


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

Здравствуйте, подскажите пожалуйста, как можно извлечь точки из контура. Контур найден таким образом:

cvFindContours( binI, storage, &contoursI, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); 
Далее я пробегаю по всем контурам и нахожу самый похожий на свой заданный контур:
CvSeq* seqM=0;

        double matchMax=1000;

        // обходим контуры изображения 

        counter=0;

		i=0; float rad; CvPoint2D32f point; 

        if(contoursI!=0){

                // поиск лучшего совпадения контуров по их моментам 

                for(CvSeq* seq0 = contoursI;seq0!=0;seq0 = seq0->h_next){

                        double match0 = cvMatchShapes(seq0, seqT, 3);

                        if(match0<matchMax){

                                matchMax = match0;

                                seqM = seq0;

                        }

			cvMinEnclosingCircle(seq0,&point,&rad); // получим окружность содержащую контур						 

		}

       }
Теперь я хочу пробежаться по всем точкам своего найденного контура. Что то типа:
CvPoint* pt;

for(int i=0; i<seqM->total;i++){			

pt=seqM->Point;				 

}

Подскажите пожалуйста, как это можно сделать

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


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

Здравствуйте, подскажите пожалуйста, как можно извлечь точки из контура. Контур найден таким образом:

cvFindContours( binI, storage, &contoursI, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); 
Далее я пробегаю по всем контурам и нахожу самый похожий на свой заданный контур:
CvSeq* seqM=0;

        double matchMax=1000;

        // обходим контуры изображения 

        counter=0;

		i=0; float rad; CvPoint2D32f point; 

        if(contoursI!=0){

                // поиск лучшего совпадения контуров по их моментам 

                for(CvSeq* seq0 = contoursI;seq0!=0;seq0 = seq0->h_next){

                        double match0 = cvMatchShapes(seq0, seqT, 3);

                        if(match0<matchMax){

                                matchMax = match0;

                                seqM = seq0;

                        }

			cvMinEnclosingCircle(seq0,&point,&rad); // получим окружность содержащую контур						 

		}

       }
Теперь я хочу пробежаться по всем точкам своего найденного контура. Что то типа:
CvPoint* pt;

for(int i=0; i<seqM->total;i++){			

pt=seqM->Point;				 

}
Подскажите пожалуйста, как это можно сделать
Попробовал таким образом:
CvPoint* pt;

std::cout<<seqM->total<<std::endl;

for(int i=0; i<seqM->total;i++){

	CvPoint* point = reinterpret_cast<CvPoint*>(cvGetSeqElem(seqM, i));

	//std::cout<<point->x;

	printf("x = %d y = %d\n ",point->x, point->y);

}

Но непонятно те ли это точки вообще?

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


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

используйте std::vector новый opencv его поддерживает.

http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html

Спасибо большое! А тот способ которым я пользовался он вообще правильный?

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


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

Добрый день!

Имеется следующая задача:

на двух изображениях, с интервалом в секунду находятся контуры:

findContours( gebiet, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

Sleep(1000);

findContours( gebiet, contours2, hierarchy2, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

Вопрос следующий:

Можно ли как нибудь быстро и просто сравнить массивы найденных контуров contours и contours2.

Если они отличаются например на 10-20 процентов то сигнал есть.

Если равны, то сигнала нет.

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

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


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

и что это значит?

можно просто пройтись по контурам и посмотреть их длину и кол-во или посчитать несколько простых моментов.

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


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

и что это значит?

можно просто пройтись по контурам и посмотреть их длину и кол-во или посчитать несколько простых моментов.

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

А если он например больше секунды не двигал, то этот этот контур считать действительным.

Длина будет одинаковая приммерно

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


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

Добрый день.Подскажите пожалуйста,как из последовательности контуров сформировать новую последовательность контуров,удовлетворяющих определенным критериям? Можно ли просто обходя исходную последовательность (найденную функцией CvFindContours),добавлять соответствующие условию контуры в новую? 
//создаем новую последовательность и выделяем под нее память
CvMemStorage* storage_1 = cvCreateMemStorage(0);
CvSeq* contours_1=cvCreateSeq( CV_SEQ_KIND_CURVE,sizeof(CvSeq),sizeof(CvContour),storage_1);

if(contours!=0){
// поиск совпадения контуров по их моментам и отсеивание по периметру
for(CvSeq* seq0 = contours;seq0!=0;seq0 = seq0->h_next){ 

double match0 = cvMatchShapes(seq0, seqT, CV_CONTOURS_MATCH_I3);

if(match0<0.5&&seq0->total>=200) 
{cvSeqPush( contours_1,seq0);}
printf(" %d match: %.2f\n", ++counter, match0);
}
}

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


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

Можно, но лучше использовать новый интерфейс (использующий cv::Mat , а не IplImage* ), как в старом делается уже не помню (откопать можно, но очень лень smile.png ). В новом используются обычные stl-овские векторы. Можно проверять критерии и собирать контуры, которые подходят. Пример работы с контурами есть в стандартных OpenCV-шных примерах.

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


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

Можно, но лучше использовать новый интерфейс (использующий cv::Mat , а не IplImage* ), как в старом делается уже не помню (откопать можно, но очень лень smile.png ). В новом используются обычные stl-овские векторы. Можно проверять критерии и собирать контуры, которые подходят. Пример работы с контурами есть в стандартных OpenCV-шных примерах.

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

то есть находить контуры функцией cvFindContours  и потом в цикле вытаскивать нужные и помещать их в массив?

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


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

Ну вот например отсеивание по площади (это просто кусок вырванный из проекта, может быть тут есть что-нибудь лишнее):

//----------------------------------------------
// Get contours centers
//----------------------------------------------
vector<cv::Point> DetectContour(Mat& img, Mat& image)
{
	vector<cv::Point> pts;
	Mat drawing( img.size(), CV_8UC3 );
	cvtColor(image,drawing,cv::COLOR_GRAY2BGR);
	Mat img8U( img.size(), CV_8UC3 );
	cv::normalize(img,img,0,255,CV_MINMAX);
	img.convertTo(img8U,CV_8UC1);
	vector<vector<Point> > contours; // Массив найденных контуров
	vector<Vec4i> hierarchy;
	findContours(img8U,contours, hierarchy, cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE, Point());
	if(contours.size()>0)
	{
		for( int i = 0; i < contours.size(); i++ )
		{
			if(contourArea(contours[i])>20)
			{				
		          // contours - просто массив с точками (можете собирать как хотите)
			}
		}
	}
	return pts;
}

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


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

 

Ну вот например отсеивание по площади (это просто кусок вырванный из проекта, может быть тут есть что-нибудь лишнее):

//----------------------------------------------
// Get contours centers
//----------------------------------------------
vector<cv::Point> DetectContour(Mat& img, Mat& image)
{
	vector<cv::Point> pts;
	Mat drawing( img.size(), CV_8UC3 );
	cvtColor(image,drawing,cv::COLOR_GRAY2BGR);
	Mat img8U( img.size(), CV_8UC3 );
	cv::normalize(img,img,0,255,CV_MINMAX);
	img.convertTo(img8U,CV_8UC1);
	vector<vector<Point> > contours; // Массив найденных контуров
	vector<Vec4i> hierarchy;
	findContours(img8U,contours, hierarchy, cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE, Point());
	if(contours.size()>0)
	{
		for( int i = 0; i < contours.size(); i++ )
		{
			if(contourArea(contours[i])>20)
			{				
		          // contours - просто массив с точками (можете собирать как хотите)
			}
		}
	}
	return pts;
}

весьма благодарен)буду разбираться.

так контур нельзя перенести как "контур"?только заново собирать из точек?

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


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

Ну почему же нельзя? Контур - массив  точек ( vector<Point> ), копируем его, в новый массив, вот и перенесли контур, и незачем тут мудрить.

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


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

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

IplImage *r = cvCreateImage(cvGetSize(imggray3), 8, 1);
IplImage *g = cvCreateImage(cvGetSize(imggray3), 8, 1);
IplImage *b = cvCreateImage(cvGetSize(imggray3), 8, 1);

IplImage *diff = cvCreateImage(cvGetSize(imggray3), 8, 3);

cvSplit(imggray3, b, g, r, 0);

IplImage *tr, *tg, *tb; // для промежуточного хранения
tr = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);
tg = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);
tb = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);

cvThreshold(r, tr, 40, 255, CV_THRESH_BINARY);
cvThreshold(g, tg, 40, 255, CV_THRESH_BINARY);
cvThreshold(b, tb, 40, 255, CV_THRESH_BINARY);

cvMerge(tb, tg, tr, 0, diff);

IplImage *clearedImage = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 3);
IplImage *temp = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 3);

IplConvKernel *element = cvCreateStructuringElementEx(10,10,1,1,CV_SHAPE_RECT);
cvMorphologyEx(clearedImage, clearedImage, temp, element, 5);
cvErode(diff, clearedImage, element);
cvDilate(clearedImage, clearedImage, element);
IplImage *dest = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 1);
cvCvtColor(diff, dest, CV_RGB2GRAY);
//find contours
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq *contours = 0; CvSeq *biggestOne;
double area = 0, biggest = 0;
cvFindContours( dest, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
if(contours != 0){
biggestOne = contours;
for(CvSeq *c = contours; c != 0; c = c->h_next) {
area = cvContourArea(c, CV_WHOLE_SEQ);
if(fabs(area) > 1000) {
if (area > biggest) {
biggest = area;
biggestOne = c;
}
}
}
cvApproxPoly(biggestOne, sizeof(CvContour), storage, CV_POLY_APPROX_DP,3,1);
cvDrawContours(&img2, biggestOne, CV_RGB(0,255,0), CV_RGB(0,255,0),0,2,8);
}

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


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

Ну например, equalizeHist или CLAHE. И то и другое есть в OpenCV, CLAHE лучше, но чтобы его использовать, как и многие другие новые функции, Вам нужно перейти на новый интерфейс (C++ a не С, как сейчас). Примеры есть в папке samples/cpp.

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


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

Ну например, equalizeHist или CLAHE. И то и другое есть в OpenCV, CLAHE лучше, но чтобы его использовать, как и многие другие новые функции, Вам нужно перейти на новый интерфейс (C++ a не С, как сейчас). Примеры есть в папке samples/cpp.

пишу на Objective-C, с opencv впервые, много не знаю через cv::Mat не получается, вылетает приложение, поэтому все делаю через IplImage, хотелось бы добиться результата как в этом коде

int main()
{
// Load test images
    Mat a;
    Mat b;

    if (a.empty() || b.empty())
        return -1;
bool isFirstFrame = true;
VideoCapture stream(-1);
while (true) {
if(isFirstFrame){
stream.read(a);
isFirstFrame = false;
} else {
if(!(stream.read(b ) //get one frame from video
break;
Mat a_blurred, b_blurred;
blur(a, a_blurred, Size(4,4));
blur(b, b_blurred, Size(4,4));

// Get absolute difference image
Mat c;
absdiff(b_blurred, a_blurred, c);
// Split image to each channels
vector<Mat> channels;
split(c, channels);

// Apply threshold to each channel and combine the results
Mat d = Mat::zeros(c.size(), CV_8UC1);
for (int i = 0; i < channels.size(); i++)
{
Mat thresh;
threshold(channels[i], thresh, 45, 255, CV_THRESH_BINARY);
d |= thresh;
}

// Perform morphological close operation to filling in the gaps
Mat kernel, e;
getStructuringElement(MORPH_RECT, Size(10,10));
morphologyEx(d, e, MORPH_CLOSE, kernel, Point(-1,-1), 5);

// Find all contours
vector<vector<Point> > contours;
findContours(e.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

// Select only large enough contours
vector<vector<Point> > intruders;
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > 10000)
intruders.push_back(contours[i]);
}

// Use the filtered blobs above to create a mask image to
// extract the foreground object
Mat mask = Mat::zeros(b.size(), CV_8UC3);
drawContours(mask, intruders, -1, CV_RGB(255,255,255), -1);
// Highlight the foreground object by darken the rest of the image
if (intruders.size())
{
b = (b/4 & ~mask) + (b & mask);
drawContours(b, intruders, -1, CV_RGB(255,255,255), 2);
}

imshow("b", b );
waitKey(27);
}
}
    return 0;
}

Подскажите в чем разница? 

int main(){
bool isFirstFrame = true;
VideoCapture stream(-1);
IplImage *imggray1 = nullptr;
Mat a, b;
while (true) {
if(isFirstFrame){
stream.read(a);
IplImage img1 = a;
imggray1 = cvCreateImage(cvGetSize(&img1), 8, 3);
cvConvertImage(&img1, imggray1, CV_GRAY2BGR);
cvSmooth(imggray1, imggray1, CV_BLUR,4,4);
isFirstFrame = false;
} else {
if(!(stream.read(b ) //get one frame from video
break;
IplImage img2 = b;
IplImage *imggray2 = cvCreateImage( cvGetSize( &img2 ), IPL_DEPTH_8U, 3);
cvConvertImage(&img2, imggray2, CV_GRAY2BGR);
cvSmooth(imggray2, imggray2, CV_BLUR, 4, 4);
IplImage *imggray3 = cvCreateImage( cvGetSize( &img2 ), IPL_DEPTH_8U, 3);

cvAbsDiff(imggray2, imggray1, imggray3);

IplImage *r = cvCreateImage(cvGetSize(imggray3), 8, 1);
IplImage *g = cvCreateImage(cvGetSize(imggray3), 8, 1);
IplImage *b = cvCreateImage(cvGetSize(imggray3), 8, 1);

IplImage *diff = cvCreateImage(cvGetSize(imggray3), 8, 3);

cvSplit(imggray3, b, g, r, 0);

IplImage *tr, *tg, *tb; // для промежуточного хранения
tr = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);
tg = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);
tb = cvCreateImage(cvGetSize(imggray3), IPL_DEPTH_8U, 1);

cvThreshold(r, tr, 45, 255, CV_THRESH_BINARY);
cvThreshold(g, tg, 45, 255, CV_THRESH_BINARY);
cvThreshold(b, tb, 45, 255, CV_THRESH_BINARY);

cvMerge(tb, tg, tr, 0, diff);

IplImage *clearedImage = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 3);
IplImage *temp = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 3);

IplConvKernel *element = cvCreateStructuringElementEx(10,10,1,1,CV_SHAPE_RECT);
cvMorphologyEx(clearedImage, clearedImage, temp, element, 5);
cvErode(diff, clearedImage, element);
cvDilate(clearedImage, clearedImage, element);
IplImage *dest = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 1);
cvCvtColor(diff, dest, CV_RGB2GRAY);
cvEqualizeHist(dest, dest);
cvShowImage("Dest", dest);
//find contours
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq *contours = 0;
double area = 0;
cvFindContours( dest, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
if(contours != 0){
for(CvSeq *c = contours; c != 0; c = c->h_next) {
area = cvContourArea(c, CV_WHOLE_SEQ);
if(fabs(area) > 1000) {
cvApproxPoly(c, sizeof(CvContour), storage, CV_POLY_APPROX_DP,3,1);
cvDrawContours(&img2, c, CV_RGB(0,255,0), CV_RGB(0,255,0),0,2,8);
}
}
}

cvShowImage("Original2", &img2);
cvReleaseImage(&temp);
cvReleaseImage(&r);
cvReleaseImage(&g);
cvReleaseImage(&b );
cvReleaseImage(&tr);
cvReleaseImage(&tg);
cvReleaseImage(&tb);
cvReleaseImage(&clearedImage);
cvReleaseImage(&dest);
cvReleaseImage(&diff);
cvReleaseImage(&imggray2);
cvReleaseImage(&imggray3);
cvReleaseMemStorage(&storage);
waitKey(27);
}
}
    return 0;

}
 

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


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

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


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

Здравствуйте! Я хотела бы узнать. После того как найдены контуры с помощью cvFindContours, как можно узнать центр фигуры, которую каждый контур обводит?

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


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

Если центр масс, тогда смотрите здесь:

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


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

Добрый день. Интересует следующий вопроса. Как определить входит ли определённая координата в этот контур или она за его пределами. Например в окружности стоит точка с определёнными координатами, хотелось бы узнать она внутри контура или же нет.

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


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

На сколько я понял pointPolygonTest работает с cv:Mat. а для IplImage есть что-то подобное? Или как мне использовать это в моём случае. Контур у меня ищется вот таким образом

//находим контуры
		
        CvMemStorage* storage = cvCreateMemStorage(0);
        CvSeq* contours=0;

      
		//IplImage* crugi_contur= NULL;
		CvSize ImageSize = cvSize(713, 713);
		crugi_contur = cvCreateImage(ImageSize, IPL_DEPTH_8U, 3);
        int contoursCont = cvFindContours( crugi, storage,&contours,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_TC89_L1, cvPoint(0,0));
        // нарисуем контуры
                cvDrawContours( crugi_contur, contours,CV_RGB(0,255,0) ,CV_RGB(0,255,0),1, 2, CV_AA, cvPoint(0,0) );
		
        cvShowImage("crugi_contur", crugi_contur);

Уважаемые знатоки, подскажите пожалуйста.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×