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

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

Recommended Posts

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

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

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

получаете список контуров, затем выделяете изображение под размер(cvBoundRect) первого контура,делаете новое окно- выводите 1-ый контур через DrawContours, берете 2-ой контур и делаете все тоже самое только размер изображения будет складываться уже из размеров уже 2-х cvBoundRect контуров(для кажого конутра создаете изображение а потов в выходное копируете с помощью cvCopy и cvSetImageROI).

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

хаф будет скорее всего не точен.

chamfer matching поможет найти положение объекта, но сравнивать объекты между собой надо будет каким то другом методом.

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


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

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

хаф будет скорее всего не точен.

chamfer matching поможет найти положение объекта, но сравнивать объекты между собой надо будет каким то другом методом.

Окружности даже чуть-чуть соприкасаются и уже считаются одним контуром. Может все таки как-то можно с помощью Хафа их разделять на отдельные окружности/контуры?

Прикрепил картинки до и после работы программы.

Исходник.bmp

Результат.bmp

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


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

Ну сразу бы картинку прикрепили :)

Заливаем фон FloodFill ом белым цветом. Дальше Threshold по черному :) и получим набор хорошо отделенных друг от друга окружностей.

PS: Проект с открытым кодом на основе opencv: http://db.cse.ohio-state.edu/CellTrack/

не совсем то, но может пригодится.

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


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

Ты в режиме компиляции 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). Иначе получишь ошибку освобождения памяти - твоя программа упадёт при выходе из функции.

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

Добрый день, у меня проблема осталась пока не решённой

в проект в дополнительные зависимости я добавляю

C:\OpenCV2.2\lib\opencv_core220d.lib

C:\OpenCV2.2\lib\opencv_highgui220d.lib

C:\OpenCV2.2\lib\opencv_video220d.lib

C:\OpenCV2.2\lib\opencv_ml220d.lib

C:\OpenCV2.2\lib\opencv_legacy220d.lib

C:\OpenCV2.2\lib\opencv_imgproc220d.lib

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

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


Mat ret = imread("1_0.jpg");

imshow("test",ret);

проект выбрасывал исключение

Необработанное исключение в "0x755fb9bc" в "testApp.exe": Исключение Microsoft C++: cv::Exception по адресу 0x0032ea70..

Необработанное исключение в "0x0049ed66" в "testApp.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000018".

с-шный интерфейс работает при этом всё ок.

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


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

Надо смотреть. Мне в таких случаях помогает отладчик - просто смотрю что и где падает.

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


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

Запустил проект, который на первой странице этой ветки, и не понял:

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

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

Может сравнение идет по площадям или по длине точек контура?

Проект интересный, хотелось бы разобраться :mellow: .

post-4351-0-77662200-1313847532_thumb.jp

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


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

Все правильно. Посмотрите на цифры, у квадратов они очень близкие по значению. У кругов будут очень близко к нулю (к нулевому контуру). Фигуры симметричные. К тому же, квадрат - это грубое приближение круга :rolleyes: , поэтому значения достаточно близкие. А порог когда контур рисуется красным я устанавливал эмпирически (от балды).

Если взять фигуры посложнее (вытянутые, или составные, или человечеки см. http://www.compvision.ru/forum/index.php?showtopic=6 ) значения будут различаться сильнее.

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


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

Все правильно. Посмотрите на цифры, у квадратов они очень близкие по значению. У кругов будут очень близко к нулю (к нулевому контуру). Фигуры симметричные. К тому же, квадрат - это грубое приближение круга :rolleyes: , поэтому значения достаточно близкие. А порог когда контур рисуется красным я устанавливал эмпирически (от балды).

Если взять фигуры посложнее (вытянутые, или составные, или человечеки см. http://www.compvision.ru/forum/index.php?showtopic=6 ) значения будут различаться сильнее.

Угу, понятно. А вот я решил просчитать инварианты Ху вот таким образом cvGetHuMoments(&moments,&hu_moments).

Подскажите, как сравнить с помощью cvMatchShapes два объекта по их 7 инвариантам?

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

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


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

http://recog.ru/blog/opencv/11.html

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

почему более точное? ху моменты обеспечивают инвариантность это и + и -.

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


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

Товарищи форумчане!

Кто разбирается в моментах, объясните, плиз, в функции cvMatchShapes( Templ, result,CV_CONTOURS_MATCH_I1),

где последний параметр функции,то есть метод сравнения, может принимать 3 значения:

CV_CONTOURS_MATCH_I1

256a09.jpg

CV_CONTOURS_MATCH_I2

fc7291.jpg

CV_CONTOURS_MATCH_I3

ebc204.jpg

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

Из какого уравнения выведены, по какому принципу идет сравнение?

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

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


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

Это просто различные способы измерения расстояния между точками. Каждая точка имеет 7 координат (7-ми мерное пространство). Похожесть объектов характеризуется величиной расстояния между точкой, характеризующей один объект и точкой характеризующей другой объект. Вот, например, L1 метрика - это так называемое Манхэттенское расстояние или Taxicab metric, L2 - Евклидово расстояние (привычное для нас). Большинство популярных метрик являются частными случаями метрикиМинковского.

В данном случае используется L1 метрика (первый случай - в качестве координат используются величины обратные значениям моментов (в качестве координат мы вольны выбирать любые величины), иногда это удобно.

Во втором случае обычная L1 метрика.

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

Можете придумать свою метрику :) только посмотрите свойства метрики здесь например.

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


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

как представлять контуры?(т.е. просто набор координат точек например или точка+ угол поворота (шаг фиксированный))

и как их выводить?(библиотеки, средства)

желание сделать, что то большее, есть исходя из того, что в opencv контур представлен как chain code(т.е. на дискретных данных)

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

(т.е. наверно можно увеличить его в несколько раз, а потом сгладить или перевести его в нужное представление(в данные), а выводить потом все равно на дискретное поле) или есть какие то ограничения?

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


Ссылка на сообщение
Поделиться на других сайтах
Вот тут мы обсуждали немного представление контуров. OpenCV поддрерживает некоторые из них: CV_CHAIN_CODE - код Фримана, CV_CHAIN_APPROX_NONE точками и т.д.

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


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

openframeworks содержит вполне юзабельные реализации работы с контурами и кривыми. См. например в директории OpenFrameworks\libs\openFrameworks\graphics\ в файлах ofPath.cpp и ofPolyline.cpp. А точки туда можно из аппроксимации (opencv-шной) поставлять. См. тему про Unicode шрифты, я там как раз кусок из open frameworks использовал.

PS: Еще по работе с кривыми (сплайны): http://www.tinaja.com/cubic01.asp

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


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

В некоторых примерах перед тем как применить cvFindContours, применяют ещё и cvCanny. Какой смысл так делать?

  • Like 1

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


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

Канни применяется как способ бинаризации изображения. Если изображение является сканированным чёрно-белым текстом, то применять его незачем. А, например, при поиске автомобильного номера можно применить Канни, поиск контуров и распознавать подряд идущие контуры одинакового размера.

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


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

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

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

т.е. по сути наверно можно оперировать и так.

а чем выгодны сплайны?

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


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

Вот тут на форуме нашёл:

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));

Изображение, вроде как, до cvCanny были чёрно-белым

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


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

Сравни контуры до и после Канни.

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


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

На сколько я могу себе это представить, то после Канни, findContours просто найдёт в два раза больше контуров =\

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


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

Наконец-то я написал "распознаватель" текста с помощью моментов. Работает быстро, точно, но правда тестировал на 15 знаках (вращал текст на угол до 90 градусов). И вот в чём проблема: иногда 6 определяется как 9, а иногда наоборот. Поэтому нужно проверять вращение. Как можно организовать?

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


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

А как Вы сами это определяете? :)

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

  • Like 1

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


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

Если нет готовой функции, то можно просто ткнуть меня в статью про хранение контуров в OpencV...

Тут перечитал тему про то, как следует подавать контур нейросетям. Там возник такой же вопрос, но тема после этого умерла =\

Спасибо.

П.с. Нечаянно создал такую же тему в нейросетях. Удалить не смог...

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


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

Контуры в версии 2.3 (не помню с какой точно) функцией нахождения контуров выдаются в виде вектора векторов, и доступ к элементам осуществляется как к обычному массиву (i-контур, j-точка).

Например (кусок, масштабирующий контуры):

		for(int i=0;i<contours.size();i++)
{
for(int j=0;j<contours[i].size();j++)
{
contours[i][j].x=(float)contours[i][j].x/64.0;
contours[i][j].y=(float)contours[i][j].y/64.0;
}
} [/code]

Для представления в классификаторах, и нейросетях обычно все координаты контура вытягивают в один вектор, сначала все координаты х, затем y, хотя это и не особо важно. Контуры, так же желательно центровать, отмасштабировать (хотя бы по периметру), и выровнять оси (например по главной оси инерции). Советую посмотреть в поисковиках информацию по ключевым словам procrustes alignment.

  • Like 1

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


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

Спасибо.

А зачем мне их центровать? Я всё равно собираюсь вектор-контур строить =\

И не понял, зачем мне нужно выравнивать оси.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×