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

Распознавание геометрических форм

Recommended Posts

Здравствуйте, я только начал изучать OpenCV и передо мной стоит такая задача: нужно на изображении распознать геометрические формы, т.е.: прямоугольник, окружность, треугольник, стрелка и т.д., затем найти параметры этих фигур(радиус, длина, координаты и т.д.) и записать это всё в XML. Хотел бы узнать с чего мне стоит начать, про какие алгоритмы почитать, может быть есть какие нибудь готовые шаблоны, которые можно было бы доработать, подскажите пожалуйста. Спасибо.

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


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

Здравствуйте! Разбираюсь с этой задачей и изучил примеры которые вы прислали, в итоге получается определить фигуру по заданному исходному контуру(но с плохой точностью). Использовал функцию cvMatchShapes, которая сравнивает фигуры по их моментам. Но как определить параметры фигуры (например радиусы, длины, положение на картинке) непонятно.. подскажите пожалуйста. Скриншот программы в прикреплённых файлах.

#include <cv.h>

#include <highgui.h>

#include <stdlib.h>

#include <stdio.h>


// сравнение объектов по моментам их контуров 

void testMatch(IplImage* original, IplImage* templ)

{

        assert(original!=0);

        assert(templ!=0);


        printf("[i] test cvMatchShapes()\n");


        IplImage* src=0;

		IplImage* dst=0;


        src=cvCloneImage(original);



        IplImage* binI = cvCreateImage( cvGetSize(original), 8, 1);

        IplImage* binT = cvCreateImage( cvGetSize(templ), 8, 1);

		printf("No problem!");



        // заведём цветные картинки

        IplImage* rgb = cvCreateImage(cvGetSize(original), 8, 3);

        cvConvertImage(src, rgb, CV_GRAY2BGR);

        IplImage* rgbT = cvCreateImage(cvGetSize(templ), 8, 3);

        cvConvertImage(templ, rgbT, CV_GRAY2BGR);


        // получаем границы изображения и шаблона

        cvCanny(src, binI, 50, 200);

        cvCanny(templ, binT, 50, 200);


        // показываем

        //cvNamedWindow( "cannyI", 1 );

        //cvShowImage( "cannyI", binI);


        //cvNamedWindow( "cannyT", 1 );

		//cvShowImage( "cannyT", binT);


        // для хранения контуров

        CvMemStorage* storage = cvCreateMemStorage(0);

        CvSeq* contoursI=0, *contoursT=0;


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

        int contoursCont = cvFindContours( binI, storage, &contoursI, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


        // для отметки контуров

        CvFont font;

        cvInitFont(&font, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0);

        char buf[128];

        int counter=0;


		int i = 0;

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

        if(contoursI!=0){

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

                        // рисуем контур

                        cvDrawContours(rgb, seq0, CV_RGB(255,216,0), CV_RGB(0,0,250), 0, 1, 8); 

                        // выводим его номер

						i+=10;

                         float rad;CvPoint2D32f point;

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

						point.x = point.x + i;

                        cvPutText(rgb, itoa(++counter, buf, 10), cvPointFrom32f(point), &font, CV_RGB(0,255,0));

                }

        }

        // показываем

        cvNamedWindow( "cont", 1 );

        cvShowImage( "cont", rgb );


        cvConvertImage(src, rgb, CV_GRAY2BGR);


        // находим контуры шаблона

        cvFindContours( binT, storage, &contoursT, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


        CvSeq* seqT=0;

        double perimT = 0;


        if(contoursT!=0){

                // находим самый длинный контур 

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

                        double perim = cvContourPerimeter(seq0);

                        if(perim>perimT){

                                perimT = perim;

                                seqT = seq0;

                        }

                        // рисуем

                        cvDrawContours(rgbT, seq0, CV_RGB(255,216,0), CV_RGB(0,0,250), 0, 1, 8); // рисуем контур

                }

        }

        // покажем контур шаблона

        cvDrawContours(rgbT, seqT, CV_RGB(52,201,36), CV_RGB(36,201,197), 0, 2, 8); // рисуем контур

        cvNamedWindow( "contT", 1 );

        cvShowImage( "contT", rgbT );



        CvSeq* seqM=0;

        double matchM=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, CV_CONTOURS_MATCH_I3);

                        if(match0<matchM){

                                matchM = match0;

                                seqM = seq0;

                        }

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

						//point.x = point.x + i;

						//point.y = point.y + 10;

      //                  cvPutText(rgb, itoa(++counter, buf, 10), cvPointFrom32f(point), &font, CV_RGB(0,255,0));

                        printf("[i] %d match: %.2f\n", ++counter, match0);						

                }

        }

        // рисуем найденный контур

        cvDrawContours(rgb, seqM, CV_RGB(52,201,36), CV_RGB(36,201,197), 0, 2, 8); // рисуем контур


        cvNamedWindow( "find", 1 );

        cvShowImage( "find", rgb );


        // ждём нажатия клавиши

        cvWaitKey(0);


        // освобождаем ресурсы

        cvReleaseMemStorage(&storage);


        cvReleaseImage(&src);

        cvReleaseImage(&dst);

        cvReleaseImage(&rgb);

        cvReleaseImage(&rgbT);

        cvReleaseImage(&binI);

        cvReleaseImage(&binT);


        // удаляем окна

        cvDestroyAllWindows();

}


int main(int argc, char* argv[])

{

        IplImage *original=0, *templ=0;


        // имя картинки задаётся первым параметром

        char* filename = argc >= 2 ? argv[1] : "D:\\work\\DiplomApplication2\\DiplomApplication2\\kontur6.png";

        // получаем картинку

        original = cvLoadImage(filename, 0);


        printf("[i] image: %s\n", filename);

        assert( original != 0 );


        // имя шаблона задаётся вторым параметром

        char* filename2 = argc >= 3 ? argv[2] : "D:\\work\\DiplomApplication2\\DiplomApplication2\\kontur0.png";

        // получаем картинку 

        templ = cvLoadImage(filename2, 0);


        printf("[i] template: %s\n", filename2);

        assert( templ != 0 );


         /*покажем изображения*/

        /*cvNamedWindow( "original", 1 );

        cvShowImage( "original", original );

        cvNamedWindow( "template", 1 );

        cvShowImage( "template", templ );*/


        // сравнение

        testMatch(original, templ);


        // освобождаем ресурсы

        cvReleaseImage(&original);

        cvReleaseImage(&templ);

        // удаляем окна

        cvDestroyAllWindows();

        return 0;

}

post-6508-0-90884200-1368376751_thumb.pn

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


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

Зависит от того что нужно измерить.

В OpenCV есть функции для: поиска габаритного прямоугольника, поиска описанного вокруг фигуры эллипса, расчет выпуклой оболочки (convex hull), поиск осей инерции, моментов, поиск окружностей, в примерах есть поиск прямоугольников, ну и много еще чего.

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


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

Зависит от того что нужно измерить.

В OpenCV есть функции для: поиска габаритного прямоугольника, поиска описанного вокруг фигуры эллипса, расчет выпуклой оболочки (convex hull), поиск осей инерции, моментов, поиск окружностей, в примерах есть поиск прямоугольников, ну и много еще чего.

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

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


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

Поищите в примерах squares.cpp и houghcircles.cpp (папка samples/cpp/).

Думаю объединив их получите то, что хотите.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×