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

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

Recommended Posts

Можно ли идентифицировать объекты на изображении, имея готовые контуры этих объектов?

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


Ссылка на сообщение
Поделиться на других сайтах
Можно ли идентифицировать объекты на изображении, имея готовые контуры этих объектов?

Можно, например как здесь: http://www.compvision.ru/forum/index.php?showtopic=6

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


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

Не могли бы Вы объяснить, что означают слова: "Проект находит контуры и выводит степень их похожести, сравнение идет с первым найденным контуром...". Получается мы находим на картинке контуры объектов, запоминаем их...а с чем сравниваем, с теми же объектами что ли?

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


Ссылка на сообщение
Поделиться на других сайтах
Не могли бы Вы объяснить, что означают слова "Проект находит контуры и выводит степень их похожести, сравнение идет с первым найденным контуром...". Получается мы находим на картинке контуры объектов, запоминаем их...а с чем сравниваем, с теми же объектами что ли?

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

PS: просто запустите пример, предварительно нарисовав на бумаге разные (и одинаковые) фигуры и многое должно проясниться :)

ЗЫ: вообще то он выводит степень их непохожести (моя опечатка) :) контур, с которым идет сравнение имеет значение 0.

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


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

Тогда такой вопрос: если мы в какой-то момент сохранили контур для сравнения, то при изменении расстояния до плоскости, в которой находится контур, он не всегда будет обнаруживаться?

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


Ссылка на сообщение
Поделиться на других сайтах
Тогда такой вопрос: если мы в какой-то момент сохранили контур для сравнения, то при изменении расстояния до плоскости, в которой находится контур, он не всегда будет обнаруживаться?

Обнаружение (выделение из изображения) контура не зависит от алгоритмов сравнения.

Я так понял, что Вы имеете ввиду изменение масштаба контура.

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

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


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

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

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


Ссылка на сообщение
Поделиться на других сайтах
Скажите, пожалуйста, существуют ли какие-нибудь численные характеристики для отличия геометрии контуров. Т.е. есть ли какая-то численная характеристика, отличающая контур в форме круга от прямоугольного контура или контура в виде овала?

Есть - моменты, например. Можете посмотреть моменты Ху (Hu invariant или Hu moment).

Значение этого момента не чувствительно к изменению масштаба, повороту, смещению и отражению контура.

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


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

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

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


Ссылка на сообщение
Поделиться на других сайтах
Попробовал сделать следующее: создал ч/б рисунок 100*100 с окружностью по центру, нашел контур, посчитал инвариантные моменты, затем переместил эту окружность на другую позицию и получил совершенно другие значения инвариантных моментов. Почему?

Рамочку вокруг кадра наверное не удалили, а она там есть :) .

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


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

я использовал код вашей программы (ContourMatching). в ней вроде вы удалили края вокруг рамки

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


Ссылка на сообщение
Поделиться на других сайтах
я использовал код вашей программы (ContourMatching). в ней вроде вы удалили края вокруг рамки

Может версия OpenCV другая?

Если кусок кода покажете (с тестовой картинкой), попробую посмотреть поближе.

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


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

Версия opencv 1.2. Весь код, собственно, Ваша функция.... Все что я добавил, отмечено комментарием

float XC[1000]={0};
float YC[1000]={0};
float S[1000]={0};
double mt=0;
int ID=0;
int NumCont=0;
int NumCont1=0;
CvMemStorage* storage = 0;
CvSeq* contours;
CvSeq* Templ;
CvSeq* result;
storage = cvCreateMemStorage(0);
CvSeq* polygons = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
CvMoments moments;
CvHuMoments hu_moments;
//while(1)
//{
cvCvtColor(Grab, gray, CV_BGR2GRAY); // Получаем серый цвет

cvThreshold( gray, gray, 150,255,CV_THRESH_BINARY);

// Необходимо удалить белый бордюр
cvRectangle(gray, cvPoint(0,0), cvPoint(gray->width-1,gray->height-1),CV_RGB(0,0,0));
// Утолщаем контуры
cvDilate( gray, gray, 0, 1 );
// Нах. границы
cvCanny( gray, gray, 50, Val1, 5 );
// Нах. контуры
cvFindContours( gray, storage,&contours,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0))
;
//--------------
if(contours!=0)
{
NumCont=contours->total; // количество найденных контуров
}

int NC=0;
for(;contours!=0;contours = contours->h_next)
{
// Аппр. контуров полигонами
result = cvApproxPoly( contours, sizeof(CvContour), storage,CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.001, 0 );
// Площадь полигона
double area=fabs(cvContourArea(result,CV_WHOLE_SEQ));
// Объявление читалки точек
CvSeqReader reader;
// Инициализация читалки точек
cvStartReadSeq( result, &reader, 0 );
// Две точки
CvPoint pt[2];
if(area>500)
{
// Вычисляем моменты
cvMoments( result, &moments);

// Добавленный код 
cvGetHuMoments(&moments,&hu_moments);

char m = cvWaitKey(33);
if( m == 109)
{
cout<<"Hu1 = "<<hu_moments.hu1<<endl;
cout<<"Hu2 = "<<hu_moments.hu2<<endl;
cout<<"Hu3 = "<<hu_moments.hu3<<endl;
cout<<"Hu4 = "<<hu_moments.hu4<<endl;
cout<<"Hu5 = "<<hu_moments.hu5<<endl;
cout<<"Hu6 = "<<hu_moments.hu6<<endl;
cout<<"Hu7 = "<<hu_moments.hu7<<endl<<endl;
}
// Коней добавленного кода

// Центр тяжести
float xc=(moments.m10/moments.m00);
float yc=(moments.m01/moments.m00);

// Обрубаем клонов
bool ok=1;
for (int o=0;o<NC;o++)
{
if( ((xc-XC[o])*(xc-XC[o])+(yc-YC[o])*(yc-YC[o]))<10 && fabs((area-S[o])/(area+S[o]))<0.3){ok=0;}
}
//
if(ok){

// Запоминаем шаблон
if(NumCont1==0)
{Templ=cvCloneSeq(result);}
// Сравниваем с найденными контурами
mt=cvMatchShapes( Templ, result,CV_CONTOURS_MATCH_I3);

NumCont1++;
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/pi);
// Отмечаем центр
cvCircle( Grab, cvPoint(xc,yc), 3, CV_RGB(0,255,255), -1, 8, 0 );
//string str1 = str(format("%lf") % mt);
_fcvt_s(NumChar, 10, mt, 2, &Decimal, &Sign);
cvPutText( Grab,NumChar, cvPoint(xc,yc),&font, CV_RGB(255,255,0));

// Достаем точки из хранилища точек и рисуем линии
for (int i=0;i<result->total-1;i++)
{
CV_READ_SEQ_ELEM( pt[0], reader );
CV_READ_SEQ_ELEM( pt[1], reader );
if(mt>0.5){cvLine(Grab,pt[0],pt[1],CV_RGB(255,0,0));}
else{cvLine(Grab,pt[0],pt[1],CV_RGB(0,255,0));}
}
}
XC[NC]=xc;
YC[NC]=yc;
S[NC]=area;
NC++;
} // if
} // for
cvPutText( Grab,"NCont1=", cvPoint(20,20),&font, CV_RGB(255,255,0));

результат:
7f481ebeae8e.jpg

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


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

По моему все нормально, порядок цифр: e-24 до e-7 в пределах ошибки вычисления для подобных алгоритмов с типом переменных double.

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

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


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

поставлена следующая задача, найти на картинке(очень далека от идеала) определенные объекты.

решал задачу следующим образом:

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

2. задал цикл в котором готовлю картинку для поиска контура ( treshold от 0 до 255)

2.1 внутренний цикл ищет контуры сравнивая их с идеальными

2.2. получаю координаты центра

Из 16 нахожу всего 4-6.

может следует копать в другую сторону? отказаться от cvMatchShapes();

прикреплю картинку, может посоветуете чего?

каким еще методом можно эффективно искать на изображении предметы?

начал читать главу про ML в книге по OpenCV. есть сомнения, это ли мне нужно? или смотреть HMM?

16x.bmp

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


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

Ну, лица ищутся bosting'ом. Пример работает так себе.

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


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

решал задачу следующим образом:

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

2. задал цикл в котором готовлю картинку для поиска контура ( treshold от 0 до 255)

2.1 внутренний цикл ищет контуры сравнивая их с идеальными

2.2. получаю координаты центра

Из 16 нахожу всего 4-6.

а каким образом осуществляется поиск контуров для распознавания? конкретизируйте, вместе посмотрим

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


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

посмотрел как в примере с камерой, правда не знаю что за последние 2а аргумента cvFindContours

кусок

 

for(int porog=0;porog!=255;++porog){
cvSmooth( Image_1, Image_1, CV_GAUSSIAN, 5, 5, 1, 1 );
cvThreshold( Image_1, Image_1, porog, 100, CV_THRESH_BINARY_INV);
cvCanny( Image_1, Image_1, 50, 100, 5 );
int kolich=cvFindContours( Image_1, storage_img,&img_contour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,
0));


if(kolich)
Find_Cont(&Value_in,&Value_out, img_contour, Image_2);
//и переход в ф-ю, которая сравнивает все img_contour с шаблоном
}

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


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

посмотрел как в примере с камерой, правда не знаю что за последние 2а аргумента cvFindContours
кусок
for(int porog=0;porog!=255;++porog){
cvSmooth( Image_1, Image_1, CV_GAUSSIAN, 5, 5, 1, 1 );
cvThreshold( Image_1, Image_1, porog, 100, CV_THRESH_BINARY_INV);
cvCanny( Image_1, Image_1, 50, 100, 5 );
int kolich=cvFindContours( Image_1, storage_img,&img_contour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,
0));


if(kolich)
Find_Cont(&Value_in,&Value_out, img_contour, Image_2);
//и переход в ф-ю, которая сравнивает все img_contour с шаблоном
}


По поводу последних двух параметров (method и offset) в руководстве говорится (может где переврал, но немного):

* method –
Метод аппроксимации (для всех режимов, кроме CV_LINK_RUNS, который использует свою, встроенную аппроксимацию)

* CV_CHAIN_CODE - выдает контуры в цепном коде Фримана. Другие методы выдают полигонами (последовательностями вершин)
* CV_CHAIN_APPROX_NONE - полигон со ВСЕМИ точками цепного кода.
* CV_CHAIN_APPROX_SIMPLE - сжимает горизонтальные, вертикальные, и диагональные сегменты и оставляет только их конечные точки.
* CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS - один из вариантов аппроксимирующего алгоритма Teh-Chin (не спрашивайте что это smile.gif ).
* CV_LINK_RUNS - использует абсолютно другой алгоритм извлечения контуров по горизонтальным сегментам единичных точек (насколько я понял, работает по сканлайнам). Используется только с CV_RETR_LIST.

* offset – Смещение, смещает все точки контура на заданное расстояние. Это полезно когда контур извлекается с использованием ROI а анализ производится на полном изображении

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


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

Использовать cvCanny я думаю не стоит, из-за него только внутренние контуры появляются, да и для работы cvFindContours он совершенно не требуется.

А если картинка плохого качества возможно стоит использовать адаптивный порог

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


Ссылка на сообщение
Поделиться на других сайтах
Использовать cvCanny я думаю не стоит,

Согласен, он лишний.

> Пример работает так себе.

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

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


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

Убрал cvCanny стало немного лучше находить.

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

//cvAdaptiveThreshold ( Image_1, Image_1, porog,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV);

я ищу на картинке 1 объект как сочетание из 4х. найдет 1-3 из 4х кусков - считай не нашло ничего.

а Есть ли способ найти сразу целиком объект? просто контурами по-моему довольно сложно получается.

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

84471.gif

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


Ссылка на сообщение
Поделиться на других сайтах
Убрал cvCanny стало немного лучше находить.

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

//cvAdaptiveThreshold ( Image_1, Image_1, porog,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV);

я ищу на картинке 1 объект как сочетание из 4х. найдет 1-3 из 4х кусков - считай не нашло ничего.

а Есть ли способ найти сразу целиком объект? просто контурами по-моему довольно сложно получается.

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

84471.gif

Может попробовать искать отрезки?

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

Ведь линии прослеживаются достаточно четко.

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


Ссылка на сообщение
Поделиться на других сайтах
я ищу на картинке 1 объект как сочетание из 4х. найдет 1-3 из 4х кусков - считай не нашло ничего.

а Есть ли способ найти сразу целиком объект? просто контурами по-моему довольно сложно получается.

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

Пробовал так:

cvFindContours( Image_1, storage_img,&img_contour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

CvSeq* q = cvCreateSeq(4620,sizeof(CvContour),sizeof(CvPoint),storage);

for (contours!=0;contours=contours-h_next)

{

	result = cvApproxPoly(...

	CvSeqPush(q,result);

}

cvMoments(q,&moments)

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

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


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

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

Вот из хелпа:

void cvMoments(const CvArr* arr, CvMoments* moments, int binary=0)

Calculates all of the moments up to the third order of a polygon or rasterized shape.

Parameters:

* arr – Image (1-channel or 3-channel with COI set) or polygon (CvSeq of points or a vector of points)

* moments – Pointer to returned moment’s state structure

* binary – (For images only) If the flag is non-zero, all of the zero pixel values are treated as zeroes, and all of the others are treated as 1’s

The function cvMoments() calculates spatial and central moments up to the third order and writes them to moments. The moments may then be used then to calculate the gravity center of the shape, its area, main axises and various shape characeteristics including 7 Hu invariants.

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

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×