Resident 0 Жалоба Опубликовано June 14, 2011 Как узнать место положения выделенной точки? Мне нужно узнать координаты x и y. Код: //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "cv.h" #include "highgui.h" #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; CvCapture* capture = 0; IplImage *frame, *frame_copy = 0; IplImage *gray = 0; /* IplImage *frame_green = 0; IplImage *frame_blue = 0; */ int Val=0,Val1=0; // Значение переменной (для разных нужд) // Описатель шрифта (см. дальше) CvFont font; TStringList *Lst; float edge_thresh=1; void ProcessFrame( IplImage* image ); #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4) //--------------------------------------------------------------------------- // Создание API шного битмапа из интеловского RGB изображения //--------------------------------------------------------------------------- HBITMAP CreateRGBBitmap(IplImage* _Grab) { char *App; LPBITMAPINFO lpbi = new BITMAPINFO; lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbi->bmiHeader.biWidth = _Grab->width; lpbi->bmiHeader.biHeight =_Grab->height; lpbi->bmiHeader.biPlanes = 1; lpbi->bmiHeader.biBitCount = 24; lpbi->bmiHeader.biCompression = BI_RGB; lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)_Grab->width * 8) * _Grab->height; lpbi->bmiHeader.biXPelsPerMeter = 0; lpbi->bmiHeader.biYPelsPerMeter = 0; lpbi->bmiHeader.biClrUsed = 0; lpbi->bmiHeader.biClrImportant = 0; void* pBits; HBITMAP hBitmap = CreateDIBSection( NULL, lpbi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0 ); delete lpbi; if ( hBitmap ) App=(char*)pBits; long int length=0; if(_Grab->nChannels==1) // Серое или бинарное { length = _Grab->width*(_Grab->height); for (int i=0;i<_Grab->height;i++) { for (int j=0;j<_Grab->width;j++) { App[_Grab->width*3*(_Grab->height-i-1)+j*3]=_Grab->imageData[_Grab->width*(i)+j]; App[_Grab->width*3*(_Grab->height-i-1)+j*3+1]=_Grab->imageData[_Grab->width*(i)+j]; App[_Grab->width*3*(_Grab->height-i-1)+j*3+2]=_Grab->imageData[_Grab->width*(i)+j]; } } } if(_Grab->nChannels==3) // Цветное { for (int i=0;i<_Grab->height;i++) { // Копируем строчку за строчкой (переворачивая вверх ногами) memcpy(App+_Grab->width*3*(_Grab->height-i-1),_Grab->imageData+_Grab->width*3*i,_Grab->width*3); } } return hBitmap; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Функция вывода изображения на HANDLE оконного компонента //--------------------------------------------------------------------------- void APIDrawIpl(int x,int y,IplImage* _Grab,void *HANDLE) { HDC hMemDC,hDC; hDC=GetDC(HANDLE); hMemDC = CreateCompatibleDC(hDC); HBITMAP Bitmap=CreateRGBBitmap(_Grab); SelectObject(hMemDC,Bitmap); BitBlt(hDC,x,y,_Grab->width,_Grab->height,hMemDC,0,0,SRCCOPY); DeleteObject(Bitmap); DeleteDC(hMemDC); DeleteDC(hDC); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { capture = cvCaptureFromCAM(0); // Инициализация шрифта (теперь можем вывести какой-нибудь текст) cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,1,8); // Поток обработки простоя Application->OnIdle = IdleLoop; } //--------------------------------------------------------------------------- void __fastcall TForm1::IdleLoop(TObject*, bool& done) { done = false;// Поток обработки простоя if( capture ) { // Даем приказ на захват кадра if( !cvGrabFrame( capture )) goto skip; // Если удачно - получаем кадр frame = cvRetrieveFrame( capture ); if( !frame ) // Если захват не удался - пропускаем дальнейшее goto skip; // Выделяем память под копию кадра if( !frame_copy ) frame_copy = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels ); // Выделяем память под серую копию кадра if( !gray ) gray = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U,1); //********************************************************* // Если стерли то что ниже - это надо раскомментировать // frame_copy = cvCreateImage( cvSize(frame->width,frame->height), // IPL_DEPTH_8U, frame->nChannels ); // Делаем копию кадра, иначе может пропасть. // cvCopy( frame, frame_copy, 0 ); // Если стерли то что ниже - это надо раскомментировать //********************************************************* //********************************************************* // Если не нужно подгонять размер кадра - это можно стереть // Выделяем память под копию кадра if( !frame_copy ) frame_copy = cvCreateImage( cvSize(352,288), IPL_DEPTH_8U, frame->nChannels ); // Масштабируем под заданный размер cvResize( frame, frame_copy, CV_INTER_LINEAR ); // Если не нужно подгонять размер кадра - это можно стереть //********************************************************* // Обработка полученного кадра ProcessFrame( frame_copy ); } skip:; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { cvReleaseImage( &frame_copy ); cvReleaseImage( &gray ); cvReleaseCapture( &capture ); } //--------------------------------------------------------------------------- void ProcessFrame( IplImage* Grab ) { float XC[1000]={0}; float YC[1000]={0}; float S[1000]={0}; int ID=0; int NumCont=0; int NumCont1=0; CvMemStorage* storage = 0; CvSeq* contours; CvSeq* result; storage = cvCreateMemStorage(0); CvSeq* polygons = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage ); CvMoments moments; cvCvtColor(Grab, gray, CV_BGR2GRAY); // Получаем серый цвет if(Form1->CheckBox1->Checked) {cvThreshold( gray, gray, Val,255,CV_THRESH_BINARY_INV);} else {cvThreshold( gray, gray, Val,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, 0, 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); 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){ 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/M_PI); // Отмечаем центр cvCircle( Grab, cvPoint(xc,yc), 3, CV_RGB(0,255,255), -1, 8, 0 ); // Рисуем эллипс //cvPutText( Grab,(FloatToStrF(NumCont1,ffGeneral,4,3)).c_str(), 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 ); cvLine(Grab,pt[0],pt[1],CV_RGB(255,0,0)); } } XC[NC]=xc; YC[NC]=yc; S[NC]=area; NC++; } // if } // for cvPutText( Grab,("NCont1="+FloatToStrF(NumCont1,ffGeneral,4,3)).c_str(), cvPoint(20,14),&font, CV_RGB(255,255,0)); //----------------------------------------------------------------------------- APIDrawIpl(10,10,Grab,Form1->Handle); // Рисуем результат APIDrawIpl(Grab->width+10,10,gray,Form1->Handle); // Рисуем результат cvReleaseMemStorage(&storage); } void __fastcall TForm1::TrackBar1Change(TObject *Sender) { Val=TrackBar1->Position; edge_thresh=float(Val); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar2Change(TObject *Sender) { Val1=TrackBar2->Position; } //--------------------------------------------------------------------------- Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано June 14, 2011 xc,yc Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
YuliyaChuguy 1 Жалоба Опубликовано April 21, 2014 Если функция arcLength (она же cvContourPerimeter) возвращает не количество пикселей - то что подразумевается под периметром? Почему возвращается тип double? Ресурсы видела: http://docs.opencv.org/trunk/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=cv2.arclength#cv2.arcLength http://code.opencv.org/projects/opencv/repository/revisions/master/changes/modules/imgproc/src/shapedescr.cpp http://stackoverflow.com/questions/11132729/finding-length-of-contour-in-opencv Периметр контура точки, который состоит из 4-х пикселей, равен 5,65686. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 21, 2014 Если пиксели расположены рядом и горизонтально, то расстояние между ними равно 1 (это понятно). А если по-диагонали? Не будет ли разумным посчитать расстояние по теореме Пифагора как: sqrt(2)? 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах