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

Место положения точки

Recommended Posts

Как узнать место положения выделенной точки? Мне нужно узнать координаты 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;

}

//---------------------------------------------------------------------------


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


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

xc,yc

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


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

Если функция 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.

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


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

Если пиксели расположены рядом и горизонтально, то расстояние между ними равно 1 (это понятно). А если по-диагонали? Не будет ли разумным посчитать расстояние по теореме Пифагора как: sqrt(2)?

  • Like 1

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×