Smorodov 579 Жалоба Опубликовано December 28, 2011 У меня такой код без проблем работает: // test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "vector" class ob{ public: char id; //Цвет int M00,M10,M01; int Xc,Yc; ob() { M00=M10=M01=0; } void addPoint(int x, int y) { M00++; M10+=x; M01+=y; } }; int _tmain(int argc, _TCHAR* argv[]) { std::vector<ob*> bufOb; for(int i=0;i<10;i++) { bufOb.push_back(new ob); } for(unsigned int i=0;i<bufOb.size();i++) { delete bufOb[i]; } bufOb.clear(); getchar(); return 0; } [/code] Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
keenk 0 Жалоба Опубликовано December 28, 2011 Не понял... от центровка по объекту, а затем удаление массива? for(unsigned int i=0;i<bufOb.size();i++) { delete bufOb[i]; } В такой версии bufOb в 2-х случаях начинает выдавать ошибку // opencv1.cpp: определяет точку входа для консольного приложения. // #include "stdafx.h" #include <cv.h> #include <highgui.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <vector> using namespace std; // Размер картинки int width; int height; //Класс объекта class ob{ public: char id; //Цвет int M00,M10,M01; int Xc,Yc; ob(){ M00=M10=M01=0; } void addPoint(int x, int y){ M00++; M10+=x; M01+=y; } CvPoint getCenter(){ Xc=int(M10/M00); Yc=int(M01/M00); return cvPoint(Xc,Yc); } }; //---Три функции алгоритма заливки void NearPix(uchar** ptr,int x, int y, int *numStack, CvPoint *Stack, ob &Obj){ if(ptr[y][3*x]==255){ ptr[y][3*x] = 0; ptr[y][3*x+1] = 255; ptr[y][3*x+2] = 0; Stack[*numStack].x=x; Stack[*numStack].y=y; (*numStack)++; Obj.addPoint(x,y); } } void OneStep(uchar** ptr, int *numSrc, int *numDest, CvPoint *Src, CvPoint *Dest, ob &Obj){ int x,y,i; *numDest=0; for(i=0; i<*numSrc;i++){ x=Src[i].x; y=Src[i].y; NearPix(ptr,x+1,y,numDest,Dest,Obj); NearPix(ptr,x-1,y,numDest,Dest,Obj); NearPix(ptr,x,y+1,numDest,Dest,Obj); NearPix(ptr,x,y-1,numDest,Dest,Obj); } } void WaveFill(uchar** ptr,int xst, int yst, ob &Obj){ Obj.addPoint(xst,yst); ptr[yst][3*xst] = 0; ptr[yst][3*xst+1] = Obj.id; ptr[yst][3*xst+2] = 0; int numA, numB; CvPoint *stackA, *stackB; stackA=new CvPoint[10000]; stackB=new CvPoint[10000]; numA=1; stackA[0].x=xst; stackA[0].y=yst; numB=0; while(1){ if(numA>0)OneStep(ptr,&numA,&numB,stackA,stackB,Obj); else break; if(numB>0)OneStep(ptr,&numB,&numA,stackB,stackA,Obj); else break; } delete [] stackB; delete [] stackA; } IplImage* image = 0; //---Начало программы int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "E:\\1.jpg"; vector<ob*> bufOb; //Буфер объектов cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE ); image = cvLoadImage(filename,1); IplImage* frame; width = image->width; height = image->height; IplImage* buf = cvCreateImage( cvSize(width,height), 8, 3 ); uchar** ptra=new uchar*[height]; frame = cvLoadImage("E:\\1.jpg"); cvCopy(frame,buf); cvSmooth( frame, frame, CV_GAUSSIAN, 5, 5 ); uchar* ptr; //Первый прход по всем пикселям for( int y=0; y<height; y++ ){ ptr = (uchar*)(frame->imageData + y * frame->widthStep); for( int x=0; x<width; x++ ){ //Гасим всё кроме зелёного bool bGreen = ptr[3*x]+15<ptr[3*x+1]&&ptr[3*x+2]+15<ptr[3*x+1]; ptr[3*x] = ptr[3*x+1] = ptr[3*x+2] = bGreen*255; } ptra[y]=ptr; } //Рисуем рамку чёрного цвета по границе изображения //для ограничения заливки cvRectangle(frame, cvPoint(0,0), cvPoint(width-1,height-1), cvScalar(0,0,0) ); //Второй проход по всем пикселям в котором применяется заливка //для разделения объектов, причём шаг цикла это ограничение //на размер объекта for( int y=0; y<height; y+=1 ){ for( int x=0; x<width; x+=1 ){ if(ptra[y][3*x]==255){ ob* newOb; newOb = new ob; bufOb.push_back(newOb); WaveFill(ptra,x,y,bufOb[bufOb.size()-1]); // тут } } } for(int unsigned i=0; i<bufOb.size(); i++){ cvCircle (frame,bufOb[i].getCenter(),5,cvScalar(0,0,255),3,2); // тут } //Очистка буфера объектов bufOb.clear(); cvShowImage( "Example2", frame ); char c = cvWaitKey(33); cvDestroyWindow( "Example2" ); cvReleaseImage(& image); return 0; } без финальной обработки запускается, правда виснет насмерть ))) .... осталось только самый конец.... помогите закончить ))) и я отправлюсь учить c++ чувство что ошибаюсь в элементарном из за не знания =((( Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано December 28, 2011 int unsigned i=0; -> unsigned int сейчас туго соображаю, завтра посмотрю подробнее Еще лучше запуститесь под отладкой (Debug), наставьте бряков (F9) и шагайте построчно (F10), заодно и поймете как программа работает Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
keenk 0 Жалоба Опубликовано January 4, 2012 С наступившим новом годом! Собственно во всём разобрался, фильтр доделать осталась для определения нужного текста, а так всё работает, спасибо! Такой вопрос возник, а как найти белые цвет? Он вроде все 255, но по факту, когда так делаю, находятся все цвета которые есть на изображение (буквально сразу все), кроме белого... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 4, 2012 Переходите в пространство HSV ЗЫ: белый = серый - это когда R=G=B > Threshold !!! Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Виктор 0 Жалоба Опубликовано January 22, 2012 (изменено) Спасибо, очень пригодилось для понимания. А допустим мне надо выделять не одноцветный объект, а объект залитый двумя или более цветами. Примерно такой: Как лучше организовать эту операцию? Вообще как я понимаю операция выделения объекта по цвету сводиться к "убиванию" всех других цветов отличных от искомого. Допустим если выделять искомые цвета белым, то получится так, что у меня будет белый объект. Но как достоверится что белый объект является искомым объектом? Изменено January 22, 2012 пользователем Виктор Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 22, 2012 Наложить белый объект (маску) на изображение и сравнить с искомым. Можно даже по количеству попавших под маску пикселей разных цветов (по гистограмме). Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Виктор 0 Жалоба Опубликовано January 22, 2012 Наложить белый объект (маску) на изображение и сравнить с искомым. Это интересный вариант. В этом случае можно вычислить процент совпадения? Можно даже по количеству попавших под маску пикселей разных цветов (по гистограмме). Но этот интереснее, так как он позволит получать больше информации. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 22, 2012 По первому варианту. Вырезаем, приводим к фиксированному масштабу (масштабу шаблона), по маске обрезаем все лишнее, и cvMatchTemplate (или что нибудь аналогичное) по каналам (RGB или HSV). Степень совпадения выдается в численном виде. В принципе, можно нормировать яркость, вычесть одно из другого, и найти сумму элементов результата. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Cerebrum 0 Жалоба Опубликовано February 6, 2012 Доброго времени суток. Передо мной поставили практически аналогичную задачу по выделению объектов. Но есть несколько нюансов: Выделение не определенного цвета, а цветового интерва. Хотя на первое время будут использоваться изображения в оттенках серого;Существуют ограничения по площади закрашивания объектов. На первый взгляд перебор всех пикселей для поиска нужных нам объектов достаточно медленно будет производится. Вот и вопрос есть ли более оптимальный вариант именно с учетом ограничений по площади. Первоначально пришло в голову использовать cvInRangeS(). Получив бинарное изображение с картой наших выделяемых объектов, следует их отсеять по площади. Вот здесь тем же перебором пикселей для поиска объектов белого цвета к примеру как-то не оптимально использовать. Заливку осуществлять с помощью cvFloodFill(). Далее уже используя эту собранную маску можно использовать для закрашивания исходного изображения в нужный цвет. Пока писал пост пришла идея на счет контуров, попробую реализовать оба варианта и будет видно что быстрее и корректнее работает. Может у форумчан есть что-то готовое, без использования перебора пикселей, либо еще некоторые уловки для ускорения работы метода (будь то еще мне неизвестные процедуры библиотеки). P.S. Извините за ломаный язык... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано February 6, 2012 Хотя бы для эксперимента, попробуйте засечь время прохода по всем пикселям изображения, думаю результат Вас удивит Если хотите работать с цветом, то и начинайте с цветного изображения. Только переведите его перед бинаризацией в пространство HSV. Поиск контуров вполне нормальный вариант. Еще гуглите по фразе: Connected Components Labeling. Тут апплет иллюстрирующий алгоритм: http://www.cise.ufl.edu/~sahni/dsaaj/JavaVersions/applications/ImageComponentLabeling/ImageComponentLabeling.htm Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Cerebrum 0 Жалоба Опубликовано February 7, 2012 Сделал через прогон всех пикселей. Скорость приятно удивила, спасибо. В былые времена, когда начинал все с delphi, это все было в разы медленнее. На счет цвета, маловероятно что кто-то будет потом на цвет переходить. На счет преимущества HSV над RGB, пока не особо его осознаю. Может кто образумит) На счет Connected Components Labeling. Уже решал подобного рода задачи когда еще не использовал библиотеку. Меня порадовала как раз функция cvFloodFill(), которая все делает что надо, да еще как раз площадь возвращает, да и периметр, который тоже потом понадобится. Идея на счет контуров... если так посудить там так же используется перебор всех пикселей, может немного более оптимизированный, но все же. И достаточно много всего лишнего вычисляется. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах