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

Выделение стеблей от фона

Recommended Posts

Привет всем. С OpenCv вообще не знаком) Вот сижу разбираюсь уже сутки не спавши. Есть изображение такого типа

post-6357-0-85040400-1361840299_thumb.jp

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

post-6357-0-85179300-1361839990_thumb.jp

Пробовал использовать FindContours, но толкового ничего не получил.

Есть еще немного обработанное изображение. Кое как по цветовой зависимости удалось найти почти весь фон

post-6357-0-51820900-1361840352_thumb.jp

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

Подскажите, а то уже весь мозг сломал. Еще большая то проблема в том, что знаю только delphi, openCV прикрутил к нему.

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


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

Может в сторону преобразований Хафа пойти? http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html

Красный цвет можно удалить просто по RGB, если красная составляющая высокая, а потом морфологические операции применить http://habrahabr.ru/post/113626/ (например, эрозия-эрозия-дилатация-дилатация)

  • Like 1

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


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

Попробую. Спасибо. А подскажите как пройти по всем точкам контура найденного FindContours?

Очень сильно сложно не хочу делать. В принципе меня и так все устраивает только вот как удалить красные области если они больше определенно площади, ну или периметра?

Выражусь по точнее.

Мне нужно удалить сначала все большие красные области, а затем удалить все маленькие не красные области. Средствами delphi это ужас как долго и сложно, opencv быстрее работает, но я с ним не сталкивался и многие функции не могу применить. Для начала нужно просто вырезать это все. а допиливаться потом будет если потребуется.

И еще вопрос, а подскажите функцию поиска именно замкнутых контуров, а то FindConours находит и не замкнутые

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


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

vector<vector<Point> > contours;

findContours( bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );

vector<Point> contour;

//  пробегаемся по каждому контуру в наборе контуров

foreach (contour, contours) {

    //  contourArea(contour);  - вот так можете подсчитать площадь

    //  получаем доступ к каждой точке

    foreach (Point p,  contour){

        //  выполняем необходимые проверки

    }    

}

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


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

я думаю лучше делать текстурную сегментацию, если требуется еще и обучить классификатор на текстуру стеблей.

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


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

я думаю лучше делать текстурную сегментацию, если требуется еще и обучить классификатор на текстуру стеблей.

Ох для меня это темный лес, а где можно почитать? Но видите, цвета фона и стеблей очень очень похожи или это не влияет?

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


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

ну цветовая сегментация это не текстурная.

с обучением по цвету и текстуре

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

просто сегментатор на основе габора

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

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

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

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


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

ну цветовая сегментация это не текстурная.

с обучением по цвету и текстуре

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

просто сегментатор на основе габора

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

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

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

Вот я и хотел сделать постобработку сначала. Вот сейчас с ней мучаюсь) Не так уж и просто, на delphi нет цикла foreach как можно по другому достать данные пикселя в контуре? И закрасить его(удалить)?

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


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

for(int i = 0; i < contours.size(); ++i) {

// вызываем contours.at(i); и делаем что нам нужно

}

Что-то типа такого не подойдет?

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


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


for(int i = 0; i < contours.size(); ++i) {

// вызываем contours.at(i); и делаем что нам нужно

}

Что-то типа такого не подойдет?

И так не выходит. У contours нет такого свойства, есть только total, h_next,h_prev,v_next,v_prev,first,free_bloc,storage,flags,header_size,elem_size,ptr,delta_elems.

Блин ну вот засада то. Я то уж обрадовался.

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


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

Если у Вас контуры объявлены так:

vector<vector<Point> > contours;

то метод size() у него точно есть, это метод контейнера vector. И выдает количество объектов в нем.

Посмотрите здесь http://www.compvision.ru/forum/index.php?showtopic=173&st=320

(пост 328).

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


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

Если у Вас контуры объявлены так:

vector<vector<Point> > contours;

то метод size() у него точно есть, это метод контейнера vector. И выдает количество объектов в нем.

Посмотрите здесь http://www.compvision.ru/forum/index.php?showtopic=173&st=320

(пост 328).

Нет у меня описано не так у меня CvSeq* contours;

Как это обозначит в делфи вектором для opencv я и не знаю даже..

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


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



  sourceImage, grayImage, binaryImage, contourImage: PIplImage;

  storage: PCvMemStorage;

  find_contour,dsp,current,result,h_next: PCvSeq;

  find_contour_num: Integer;

  area,perim:double;

  i:integer;

  line:cvpoint;

   center:CvPoint2D32f;

 radius:float;

 p:cvPoint;

rr:CvRect;

reader:CvSeqReader;


begin

  sourceImage := cvLoadImage('source.bmp', CV_LOAD_IMAGE_ANYDEPTH or CV_LOAD_IMAGE_ANYCOLOR);

  grayImage := cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 1);

  binaryImage := cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 1);

  contourImage := cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 3);

  cvThreshold(grayImage, binaryImage, 128, 255, CV_THRESH_BINARY);

  cvCvtColor(SourceImage, grayImage, CV_BGR2GRAY);

  contourImage := cvCloneImage(sourceImage);

  cvCanny(grayImage, binaryImage, 50, 200, 3 );

  storage := cvCreateMemStorage(0);

  find_contour := nil;

  find_contour_num := cvFindContours(binaryImage,storage,@find_contour,sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_NONE,CvGetPoint(0,0));

  current:=find_contour;

  While(current<>nil)do

  begin

        perim:=cvcontourArea(current,CV_WHOLE_SEQ);

  current := current.h_next;

  end;

  cvDrawContours(contourImage,current,CV_RGB(255,216,0),CV_RGB(0,0,0),2,1,8,CvGetPoint(0, 0));

  cvShowImage('windowNameContour', contourImage);

  cvNamedWindow('windowNameContour', CV_WINDOW_AUTOSIZE);

  cvShowImage('windowNameContour', contourImage);

  cvWaitKey(0);

  cvSaveImage('DSC03631c.bmp', contourImage);

Пока что вот что у меня выходит. Могу только посчитать площади каждого контура

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


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

Так если нужно рисовать контуры, фильтруя их по площади, то нужно ввести условие сравнения площади контура с пороговым значением и внести рисование контура в цикл.

Посмотрите по ссылке которую я дал, там два варианта есть С++ и С первый с векторами, второй с CvSeq*.

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

ЗЫ: С дельфи замучаетесь. Напишите лучше DLL-ку на C и вызывайте ее из дельфи, если очень нужен дельфийский интерфейс.

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


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

Так если нужно рисовать контуры, фильтруя их по площади, то нужно ввести условие сравнения площади контура с пороговым значением и внести рисование контура в цикл.

Посмотрите по ссылке которую я дал, там два варианта есть С++ и С первый с векторами, второй с CvSeq*.

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

ЗЫ: С дельфи замучаетесь. Напишите лучше DLL-ку на C и вызывайте ее из дельфи, если очень нужен дельфийский интерфейс.

Огромное спасибо за помощь!

Да я понимаю что с делфями это ужас. Я просто в СИ ноль полный)))

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

Ой блин, только щас заметил. Мнеж нужно то выделить контуром только красные пятна, а он мне все выделяет...

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


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

http://robocraft.ru/blog/computervision/640.html

cvDrawContours посмотрите там)

То что Smorodov кинул ссылку, там отлично написано


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

        CvMemStorage* storage = cvCreateMemStorage(0);

        CvSeq* contours=0;


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

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


        assert(contours!=0);


        // обходим все контуры

        for( CvSeq* current = contours; current != NULL; current = current->h_next ){

                // вычисляем площадь и периметр контура

                double area = fabs(cvContourArea(current));

                double perim = cvContourPerimeter(current);


                // 1/4*CV_PI = 0,079577

                if ( area / (perim * perim) > 0.07 && area / (perim * perim)< 0.087 ){ // в 10% интервале

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

                        cvDrawContours(_image, current, cvScalar(0, 0, 255), cvScalar(0, 255, 0), -1, 1, 8);

                }

        }

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


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

http://robocraft.ru/blog/computervision/640.html

cvDrawContours посмотрите там)

То что Smorodov кинул ссылку, там отлично написано


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

        CvMemStorage* storage = cvCreateMemStorage(0);

        CvSeq* contours=0;


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

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


        assert(contours!=0);


        // обходим все контуры

        for( CvSeq* current = contours; current != NULL; current = current->h_next ){

                // вычисляем площадь и периметр контура

                double area = fabs(cvContourArea(current));

                double perim = cvContourPerimeter(current);


                // 1/4*CV_PI = 0,079577

                if ( area / (perim * perim) > 0.07 && area / (perim * perim)< 0.087 ){ // в 10% интервале

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

                        cvDrawContours(_image, current, cvScalar(0, 0, 255), cvScalar(0, 255, 0), -1, 1, 8);

                }

        }

Спасибо да это то я видел, по этому примеру и делал. Просто мне то нужно именно красные области.. Совсем блин сума схожу.. Лег спать просто только в 5 утра... Как раз читал robocraft про opencv

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


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

Так закрашивайте на предыдущем этапе не красным, а черным :)

Затем все что не равно нулю в 255, если нужен только красный, можно инвертировать.

Если жестко задан красный, то попиксельным сравнением с (0,0,255).

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

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


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

Так закрашивайте на предыдущем этапе не красным, а черным :)/>

Затем все что не равно нулю в 255, если нужен только красный, можно инвертировать.

Если жестко задан красный, то попиксельным сравнением с (0,0,255).

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

Ну как вариант, но проще наверное будет установить Studio 2008 и разобраться на примерах и исходниках в том что мне нужно. Это у меня диплом. Время еще есть. Да и люди желающие помочь тут тоже есть и это обнадеживает. Да и по работе с OpenCv на си примеров куча всего чего пожелаешь. А стандартные средства длфи уж очень медленные и примеров нет по моей проблеме вот и решил opencv использовать. А так как штука она полезная да и си не помешает выучит) Тем более я php знаю а они чем то схожи .

Можно будет вопросы позадавать??

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


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

Для того форум и существует, чтобы вопросы задавать )

  • Like 1

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


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

Уважаемый, Smorodov. Вы предлагали текстурную сегментацию, а где по подробнее можно про это почитать? И что именно использовать. Если не сложно можно с примерами) И желательно на русском для начала, чтоб вникнуть? Вот нашел вашу тему про SVM классификатор. А он мне подойдет? Его очень сложно обучать и использовать?

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

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

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


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

Лекции по машинному обучению здесь: http://www.compvision.ru/forum/index.php?showtopic=864

в них можно узнать побольше о классификаторах, включая SVM и RVM (8 и 9 лекции).

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

Где почитать про фильтры Габора? в интернете материал есть как их считать (да и в примере тоже).

Если кратко, то процесс можно описать так:

Создаем банк фильтров Габора на несколько масштабов и несколько ориентаций (обычно штук 40).

Применяем свертку каждым из фильтров банка к исходному изображению.

Получаем 40 изображений, на каждом из которых отклик своего фильтра.

Если мы их теперь соберем в стопку, то получится этакое 40 слойное изображение. Где каждому пикселю соответствует 40 чисел.

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

Достаем пиксели (40 мерные векторы) и метки (маска) и засовываем в классификатор (любой подходящий, не обязательно SVM).

Так формируется обучающие пары. {X,y},где X 40-мерный вектор, а y-метка (объект, или фон).

Обучаем его.

Для классификации опять применяем к изображению тот же банк фильтров.

И для каждой точки (или не для каждой а по сетке с заданным шагом), опрашиваем классификатор.

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


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

Спасибо) Почитал, но не все. Написано доступным языком,но все равно сразу то так и не вникнешь, самое знакомое - это теория вероятности и то было 4 года назад, посмотрю ваш пример. Как мне показалось сильно большой разницы нет на что именно использовать.

По поводу конкретных фото - может меняться фон незначительно, ну или значительно если чернозем или после дождя (что частенько бывает). Камера должна быть установлена на тракторе, т.е. высота съемки примерно одна, но длинна стеблей (ширина слоя) может быть разной (может и не помещаться на фото, но это уже другое дело(и у нас такое редко бывает), на данный момент главное вот такие фото обработать. А там уж. ммм. Если пойду в аспирантуру.. (ну это было отступление).

Как я понял хорошим примером будет http://www.compvision.ru/forum/index.php?showtopic=861&view=findpost&p=6146 эта програмка. буду пытаться понять.

Надеюсь на вашу помощь))

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


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

Скорее этот: http://www.compvision.ru/forum/index.php?showtopic=894

Но заранее сказать всегда сложно. Надо попробовать оба варианта, а может и совместить их.

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


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

Скорее этот: http://www.compvision.ru/forum/index.php?showtopic=894

Но заранее сказать всегда сложно. Надо попробовать оба варианта, а может и совместить их.

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

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×