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

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

Recommended Posts

А что, в таком случае, мешает сразу (в той же функции) поточечно перекинуть в глобальное хранилище (из единственного необходимого локального) контур за контуром в по мере их нахождения? Я именно это имел ввиду вначале.

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


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

А что, в таком случае, мешает сразу (в той же функции) поточечно перекинуть в глобальное хранилище (из единственного необходимого локального) контур за контуром в по мере их нахождения? Я именно это имел ввиду вначале.

Мешает незнание алгоритма того как это сделать :)

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

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


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

CvSeq* seq = cvCreateSeq( (CV_SEQ_FLAG_CLOSED|CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_POINT), sizeof(CvContour), sizeof(CvPoint), storage );
[/code] Что делает ее полигоном! дальше запись точек в последовательность.
[code] CvSeqWriter writer;
int i;
cvStartAppendToSeq( seq, &writer );

CvPoint pt = cvPoint(20,20);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(30,50);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(50,60);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
pt = cvPoint(45,30);
CV_WRITE_SEQ_ELEM( pt, writer );
printf("[%d,%d] is written\n", pt.x, pt.y );
cvEndWriteSeq( &writer );
Читать точки можно как здесь:
       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);[/code]

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


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

И еще, с С++ версией работать легче, там FindContours возвращает вектор векторов и работа с ними точно такая же как с std-шными векторами.

Вот можно посмотреть здесь: http://www.compvision.ru/forum/index.php?showtopic=625&st=0&p=4027&hl=unicode&fromsearch=1&#entry4027

И здесь: http://opencv.willowgarage.com/documentation/cpp/structural_analysis_and_shape_descriptors.html#cv-findcontours

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


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

Спасибо за подсказки.

Обязательно посмотрю в этом направлении. Сейчас стоит цель хоть немного освоиться с OpenCV на примере решения конкретных (простеньких) задач.

В частности, на данном этапе, работа с контурами. У меня будут еще вопросы. Точнее они уже есть, но пока сам поковыряюсь :)

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


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

Здравствуйте все :)

У меня снова вопрос.

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

Измученный гугель выдал мне только один вразумительный ответ. Но пример написан на Java.

Статья тут, код на Java тут. Речь там идет о детекторе границ Canny

Для OpenCV ничего подобного нет. Проверял :)

Есть ли у кого подобные решения? Или, может, всем миром перепишем это дело под C++ ?

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


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

Можно проще (меньше кода писать). Конвертируешь изображение в HSV (cvCvtColor), берёшь самый первый канал - hue, цветовой тон (cvSplit) и уже к нему применяешь Каннни.

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


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

Можно проще (меньше кода писать). Конвертируешь изображение в HSV (cvCvtColor), берёшь самый первый канал - hue, цветовой тон (cvSplit) и уже к нему применяешь Каннни.

Мысль интересная. Спасибо. Будем попробовать.

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


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

Скажите пожалуйста, как можно определить угол поворота контура относительно исходного контур?

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


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

Надо определить поворот главной оси инерции для отдельно для одного и для другого контуров, а затем, найти разницу.

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


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

Здесь есть http://www.compvision.ru/forum/index.php?showtopic=6 ищите theta

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


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

Доброго времени суток. Где можно почитать про код Фримена? В learning OpenCV ну очень непонятно.

Суть такая: нужно с помощью cvFindContours получить код Фримена и переписать его, скажем, в одномерный масив

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


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

Вот тут, например: http://msabundo.blogspot.com/2010/03/freemans-silhouette.html

А вообще, по картинке смысл должен быть понятен:

post-1-0-32437300-1321293199_thumb.png

В opencv cvFindContours выдает цепной код (он же код Фримана) если в качестве параметра metod передать константу "CV_CHAIN_CODE".

Из руководства:

CV_CHAIN_CODE outputs contours in the Freeman chain code.

Пример чтения значений из cvSeq есть в этой теме.

  • Like 1

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


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

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

int i, total = contours->total; 

	cvStartReadChainPoints((CvChain*) contours, &reader); 

	for (i = 0; i < total; i++)

	{ 

	CV_READ_SEQ_ELEM(reader.code, (*((CvSeqReader*)&(reader)))); 

	printf("%d \n", reader.code); 


	}

  • Like 1

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


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

Добрый день!

Подскажите, пожалуйста, у кого какие соображения как подсчитать количество контуров в слипшихся объектах?

post-1679-0-07477700-1322647792_thumb.jp

post-1679-0-29152700-1322647797_thumb.jp

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


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

Это тот случай (случай 1) когда без дополнительной информации об объекте не обойтись. Если это окружности, то тут все просто, если какой то другой известный объект то тоже, а по такой картинке, без доп. информации и человек может ошибаться.

Во втором случае, все контуры должны находиться нормально (однако и здесь, информация о том что мы ищем должны быть использована по-максимуму), нужно только правильно указать степень вложенности контуров, которые Вас интересуют.

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


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

image.png

как можно "восстановить" контур от разрывов и убрать двойной контур т.е. если расстояние между контурами <eps то он считается за один контур.

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

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


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

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

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


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

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

ЗЫ: Подумал еще немного, тут нужны какие то более сложные правила. Например коллинеарность смежных ребер. Может быть еще что-то.

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


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

всё равно не понятно, область одного треугольника что собой являет?

и зачем мне что то разбивать на объекты?

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

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

image.png

image.png

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


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

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

ошибку как тут, например (SSE)

http://www.machinelearning.ru/wiki/index.php?title=%D0%9B%D0%B8%D0%BD%D0%B5%D0%B9%D0%BD%D0%B0%D1%8F_%D1%80%D0%B5%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80) если она меньше заданного порога, значит контур "тонкий" и его можно заменить на отрезок.

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


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

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

еще нашел cvFindDominantPoints должна находить углы, т.е. области наибольшего закругления,но походу ф-ия не работает, у меня падает с ошибкой.

код пробовал такой.

#include "cv.h"

#include "highgui.h"


CvSeq* contours = 0;

CvSeq* dps = 0;


int main( int argc, char** argv )

{

    int i, idx;

    CvPoint p;

    CvMemStorage* storage_ct = cvCreateMemStorage(0);

    CvMemStorage* storage_dp = cvCreateMemStorage(0);

    IplImage* img = cvLoadImage("contour.bmp", CV_LOAD_IMAGE_GRAYSCALE);


    cvNamedWindow( "image" );

    cvShowImage( "image", img );


    cvFindContours( img, storage_ct, &contours, sizeof(CvContour),

        CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE );


    dps = cvFindDominantPoints( contours, storage_dp, CV_DOMINANT_IPAN, 7, 20, 9, 150 );


    contours = cvApproxPoly( contours, sizeof(CvContour), storage_ct, CV_POLY_APPROX_DP, 3, 1 );


    printf("found %d DPs and %d Contours \n", dps->total, contours->total );


    for ( i = 0; i < dps->total; i++)

    {

        idx = *(int *) cvGetSeqElem(dps, i);

        p = *(CvPoint *) cvGetSeqElem(contours, idx); 

        cvDrawCircle( img, p , 1, cvScalarAll(255) );

        printf("%d %d %d\n", idx, p.x, p.y);

    }


    cvDrawContours(img, contours, cvScalarAll(100), cvScalarAll(200), 100 );



    cvNamedWindow( "contours" );

    cvShowImage( "contours", img );


    cvWaitKey(0);

    cvReleaseMemStorage( &storage_ct );

    cvReleaseMemStorage( &storage_dp );

    cvReleaseImage( &img );


    return 0;

}

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×