//! Copy operator CBlobContour& CBlobContour::operator=( const CBlobContour &source ) { if( this != &source ) { m_startPoint = source.m_startPoint; m_parentStorage = source.m_parentStorage; if (m_contour) { cvClearSeq( m_contour ); } if (source.m_contour) { m_contour = cvCloneSeq( source.m_contour, m_parentStorage); } if( source.m_contourPoints ) { if( m_contourPoints ) cvClearSeq( m_contourPoints ); m_contourPoints = cvCloneSeq( source.m_contourPoints, m_parentStorage); } m_area = source.m_area; m_perimeter = source.m_area; m_moments = source.m_moments; } return *this; }
void ShapeClassifier::StartTraining(TrainingSet *sampleSet) { // Make a copy of the set used for training (we'll want to save it later) sampleSet->CopyTo(&trainSet); cvClearMemStorage(templateStorage); templateContours = NULL; // TODO: call into trainingset class to do this instead of accessing samplemap for (map<UINT, TrainingSample*>::iterator i = sampleSet->sampleMap.begin(); i != sampleSet->sampleMap.end(); i++) { TrainingSample *sample = (*i).second; if (sample->iGroupId == GROUPID_POSSAMPLES) { // positive sample IplImage *grayscale = cvCreateImage( cvSize(sample->fullImageCopy->width, sample->fullImageCopy->height), IPL_DEPTH_8U, 1); cvCvtColor(sample->fullImageCopy, grayscale, CV_BGR2GRAY); cvCanny(grayscale, grayscale, SHAPE_CANNY_EDGE_LINK, SHAPE_CANNY_EDGE_FIND, SHAPE_CANNY_APERTURE); cvDilate(grayscale, grayscale, 0, 2); CvMemStorage *storage = cvCreateMemStorage(0); CvSeq *sampleContours = NULL; cvFindContours(grayscale, storage, &sampleContours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS); if (sampleContours != NULL) { sampleContours = cvApproxPoly(sampleContours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 0.2, 1 ); for (CvSeq *contour = sampleContours; contour != NULL; contour = contour->h_next) { if ((contour->total > SHAPE_MIN_CONTOUR_POINTS) && (contour->flags & CV_SEQ_FLAG_CLOSED)){ if (!templateContours) { templateContours = cvCloneSeq(contour, templateStorage); } else { CvSeq *newContour = cvCloneSeq(contour, templateStorage); newContour->h_next = templateContours->h_next; templateContours->h_next = newContour; } } } } cvReleaseMemStorage(&storage); cvReleaseImage(&grayscale); } else if (sample->iGroupId == GROUPID_NEGSAMPLES) { // negative sample // do nothing for now // TODO: we could compare guesses against these as well and remove them if they match } } UpdateContourImage(); if (isOnDisk) { // this classifier has been saved so we'll update the files Save(); } // update member variables isTrained = true; }
CBlob& CBlob::operator=(const CBlob &src ) { if( this != &src ) { m_id = src.m_id; m_area = src.m_area; m_perimeter = src.m_perimeter; m_externPerimeter = src.m_externPerimeter; m_meanGray = src.m_meanGray; m_stdDevGray = src.m_stdDevGray; m_boundingBox = src.m_boundingBox; m_ellipse = src.m_ellipse; m_originalImageSize = src.m_originalImageSize; // clear all current blob contours ClearContours(); if( m_storage ) cvReleaseMemStorage( &m_storage ); m_storage = cvCreateMemStorage(); m_externalContour = CBlobContour(src.m_externalContour.GetStartPoint(), m_storage ); if( src.m_externalContour.m_contour ) m_externalContour.m_contour = cvCloneSeq( src.m_externalContour.m_contour, m_storage); m_internalContours.clear(); // copy all internal contours if( src.m_internalContours.size() ) { m_internalContours = t_contourList( src.m_internalContours.size() ); t_contourList::const_iterator itSrc; t_contourList::iterator it; itSrc = src.m_internalContours.begin(); it = m_internalContours.begin(); while (itSrc != src.m_internalContours.end()) { *it = CBlobContour((*itSrc).GetStartPoint(), m_storage); if( (*itSrc).m_contour ) (*it).m_contour = cvCloneSeq( (*itSrc).m_contour, m_storage); it++; itSrc++; } } } return *this; }
CvSeq *reghand::filthull(CvSeq *hullseq) { int thresh=handcenter.y; CvSeq *filtedhullseq=cvCloneSeq(hullseq); cvClearSeq(filtedhullseq); for (int i=0;i<hullseq->total;i++) { CvPoint** data=CV_GET_SEQ_ELEM(CvPoint*,hullseq,i); CvPoint currpt=**data; if(currpt.y<thresh) cvSeqPush(filtedhullseq,data); ; } return filtedhullseq; }
CvSeq *reghand::elimNeighborHulls(CvSeq *hullseq) { int disthreshold=handradis/3; CvSeq *filtedhullseq=cvCloneSeq(hullseq); if(hullseq->total<=1) return filtedhullseq; cvClearSeq(filtedhullseq); CvPoint **curdata;CvPoint currpt,nextpt; for(int i=0;i<hullseq->total-1;i++) { curdata=CV_GET_SEQ_ELEM(CvPoint*,hullseq,i); currpt=**curdata; nextpt=**CV_GET_SEQ_ELEM(CvPoint*,hullseq,i+1); double distance=sqrt(pow(double(currpt.x-nextpt.x),2)+pow(double(currpt.y-nextpt.y),2)); if(distance>disthreshold) cvSeqPush(filtedhullseq,curdata); } // if(hullseq->total==2)return filtedhullseq; curdata=CV_GET_SEQ_ELEM(CvPoint*,hullseq,hullseq->total-1); currpt=**curdata; nextpt=**CV_GET_SEQ_ELEM(CvPoint*,hullseq,0); double distance=sqrt(pow(double(currpt.x-nextpt.x),2)+pow(double(currpt.y-nextpt.y),2)); if(distance>disthreshold) cvSeqPush(filtedhullseq,curdata); return filtedhullseq; }
/* * * Creates a worm polygon object from a CvSeq of Points. * This will clone the CvSeq and copy it into the memory storage * specified */ WormPolygon* CreateWormPolygonFromSeq(CvMemStorage* memory,CvSize GridSize,CvSeq* points){ WormPolygon* myPoly=(WormPolygon*) malloc(sizeof(WormPolygon)); myPoly->Points=cvCloneSeq(points,memory); myPoly->GridSize=GridSize; return myPoly; }
CvSeq * cvCloneSeq_wrap(const CvSeq * seq , CvMemStorage * storage ){ return cvCloneSeq(/*const*//*CvSeq*//***/seq , /*CvMemStorage*//***/storage); }
void Distinguish::FunctionSwitch(CvSeq* circles){ /* ThreeButtonsCombination SwitchCase=1; MouseMove SwitchCase=2; Combination SwitchCase=3; TwoFingersMouse SwitchCase=4; ThreeFingerMouse SwitchCase=5; */ for(int i=0;i<circles->total;i++){//if fingers are not in keyboard area,that must be mouse action float* p=(float*)cvGetSeqElem(circles,0); if(cvRound(p[0])<65 || cvRound(p[0])>590 ||cvRound(p[1])<35||cvRound(p[1])>410){ mouse.MouseGesture(circles); SwitchCounter=0; SwitchCase=0; return; } } SwitchCounter++; if(SwitchCounter==1){//initialize circlesTemp=cvCloneSeq(circles,NULL); } switch (circles->total){//To switch amont different numbers of circles case 0://if zero finger circle,pass this to both and they will have corresponding actions pattern.estimation(circles); MouseMoveToLeftClick++; keyboard.OutputKey(circles); mouse.MouseGesture(circles); SwitchCounter=0; SwitchCase=0; if(MouseMoveToLeftClick>=10){//count for left click MouseMoveToLeftClick=0; SingleClick=false; } break; case 1: pattern.estimation(circles); int PointTemp[2]; int Point[2]; if(SwitchCase==2){ mouse.MouseGesture(circles); break; } if(SingleClick==true && MouseMoveToLeftClick!=0){ mouse.MouseGesture(circles); MouseMoveToLeftClick=0; break; } if(circlesTemp->total==1 && circles->total==1){ float* p=(float*)cvGetSeqElem(circlesTemp,0); PointTemp[0]=cvRound(p[0]); PointTemp[1]=cvRound(p[1]); float* q=(float*)cvGetSeqElem(circles,0); Point[0]=cvRound(q[0]); Point[1]=cvRound(q[1]); } if(abs(Point[0]-PointTemp[0])<10 && abs(Point[1]-PointTemp[1])<10){ SwitchCase=1; keyboard.OutputKey(circles); break; }else if((abs(Point[0]-PointTemp[0])>10 || abs(Point[1]-PointTemp[1])>10)){ SwitchCase=2; SingleClick=true; mouse.MouseGesture(circles); break; } case 2: if(SwitchCase==3){ keyboard.OutputKey(circles); break; }else if (SwitchCase==4){ mouse.MouseGesture(circles); break; } if(circlesTemp->total==1&& circles->total==2){ keyboard.OutputKey(circles); SwitchCase=3; break; }else{ mouse.MouseGesture(circles); SwitchCase=4; break; } case 3: if(SwitchCase==1){ keyboard.OutputKey(circles); break; }else if (SwitchCase==5){ mouse.MouseGesture(circles); break; } if(circlesTemp->total==2&& circles->total==3){ keyboard.OutputKey(circles); SwitchCase=1; break; }else{ mouse.MouseGesture(circles); SwitchCase=5; break; } default://more then three fingers are all mouse actions mouse.MouseGesture(circles); SwitchCounter=0; SwitchCase=0; break; } circlesTemp=cvCloneSeq(circles,NULL); }
////////////////////// // // 원 검출 // ////////////////////// void ColorTracking::draw_circle(IplImage* image) { CvSeq* m_circle = NULL; // 원 정보 CvMemStorage* storage1 = NULL; // 메모리 할당 //검출된 원을 위한 메모리 공간 할당 storage1 = cvCreateMemStorage(0); //원 갯수 저장 변수 circle_cnt = 0; //원의 중심점을 검출하기 위한 누산기의 해상도 // 1이면 입력영상과 같은 크기, 2이면 입력 영상의 가로/세로의 반크기의 누산기 double dp = 1.5; double min_dist = 300; //검출된 원의 중심 사이의 최소거리.작을 수록 많은 원이 검출 됨-? double cannyThreshold = 100; //cvCanny 함수 임계값 double accThreshold = 50; //cvCanny 함수 축적평면의 임계값 int min_radius = 50; //최소 반지름 int max_radius = 150; //최대 반지름 int cx, cy = 0; //소스영상, 메모리스토리지 포인터, 메소드인자, 영상의 해상도, 인접한 두 원사이의 최소거리 m_circle = cvHoughCircles(image, storage1, CV_HOUGH_GRADIENT, dp,min_dist, cannyThreshold, accThreshold, min_radius, max_radius); //원이 1개 라도 있으면 if(m_circle->total >0 ) { // 데이터를 내보내기 위한 전역 선언한 시퀸스로 복사 circles = cvCloneSeq(m_circle, storage0); //원 그리기 for(int k = 0; k < m_circle->total; k++) { float* circle; int radius; //검출된 원을 저장한 circles에서 원의 파라미터를 circle에 저장 //원의 중심 좌표 및 반지름이 배열에 순서대로 저장됨 circle = (float*)cvGetSeqElem(m_circle, k); cx = cvRound(circle[0]); //중심점 x 좌표 cy = cvRound(circle[1]); //중심점 y 좌표 radius = cvRound(circle[2]); //반지름 //원그리기 if(radius > min_radius && radius < max_radius) { //중심점 cvCircle(m_orig_img, cvPoint(cx, cy), 3, CV_RGB(240,0,255), -1, 8, 0); //검출라인 cvCircle(m_orig_img, cvPoint(cx, cy), radius, CV_RGB(255,255,255), 3, 8, 0); } } } else // 원이 없으면 { circles = NULL; circle_cnt = 0; } cvReleaseMemStorage(&storage1); }
/* * Smooths, thresholds and finds the worms contour. * The original image must already be loaded into Worm.ImgOrig * The Smoothed image is deposited into Worm.ImgSmooth * The thresholded image is deposited into Worm.ImgThresh * The Boundary is placed in Worm.Boundary * */ void FindWormBoundary(WormAnalysisData* Worm, WormAnalysisParam* Params){ /** This function currently takes around 5-7 ms **/ /** * Before I forget.. plan to make this faster by: * a) using region of interest * b) decimating to make it smaller (maybe?) * c) resize * d) not using CV_GAUSSIAN for smoothing */ /** Smooth the Image **/ TICTOC::timer().tic("cvSmooth"); cvSmooth(Worm->ImgOrig,Worm->ImgSmooth,CV_GAUSSIAN,Params->GaussSize*2+1); TICTOC::timer().toc("cvSmooth"); /** Dilate and Erode **/ // cvDilate(Worm->ImgSmooth, Worm->ImgSmooth,NULL,3); // cvErode(Worm->ImgSmooth, Worm->ImgSmooth,NULL,2); /** Threshold the Image **/ TICTOC::timer().tic("cvThreshold"); cvThreshold(Worm->ImgSmooth,Worm->ImgThresh,Params->BinThresh,255,CV_THRESH_BINARY ); TICTOC::timer().toc("cvThreshold"); /** Dilate and Erode **/ if (Params->DilateErode==1){ TICTOC::timer().tic("DilateAndErode"); cvDilate(Worm->ImgThresh, Worm->ImgThresh,NULL,3); cvErode(Worm->ImgThresh, Worm->ImgThresh,NULL,2); TICTOC::timer().toc("DilateAndErode"); } /** Find Contours **/ CvSeq* contours; IplImage* TempImage=cvCreateImage(cvGetSize(Worm->ImgThresh),IPL_DEPTH_8U,1); cvCopy(Worm->ImgThresh,TempImage); TICTOC::timer().tic("cvFindContours"); cvFindContours(TempImage,Worm->MemStorage, &contours,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE,cvPoint(0,0)); TICTOC::timer().toc("cvFindContours"); CvSeq* rough; /** Find Longest Contour **/ TICTOC::timer().tic("cvLongestContour"); if (contours) LongestContour(contours,&rough); TICTOC::timer().toc("cvLongestContour"); cvReleaseImage(&TempImage); /** Smooth the Boundary **/ if (Params->BoundSmoothSize>0){ TICTOC::timer().tic("SmoothBoundary"); CvSeq* smooth=smoothPtSequence(rough,Params->BoundSmoothSize,Worm->MemStorage); Worm->Boundary=cvCloneSeq(smooth); TICTOC::timer().toc("SmoothBoundary"); } else { Worm->Boundary=cvCloneSeq(rough); } }
void Determine::FunctionSwitch(CvSeq* circles){ /* KeyboardClick SwitchCase=1; MouseMove SwitchCase=2; Combination SwitchCase=3; RightClick SwitchCase=4; LeftClick SwitchCase=5; */ for(int i=0;i<circles->total;i++){ float* p=(float*)cvGetSeqElem(circles,0); if(cvRound(p[0])<70 || cvRound(p[0])>590 ||cvRound(p[1])<60||cvRound(p[1])>430){ JudgementMouse(circles); SwitchTemp=0; SwitchCase=0; return; } } SwitchTemp++; if(SwitchTemp==1){ circlesTemp=cvCloneSeq(circles,NULL); } switch (circles->total){ case 0: MouseMoveToLeftClick++; keyboard.OutputKey(circles); JudgementMouse(circles); SwitchTemp=0; SwitchCase=0; if(MouseMoveToLeftClick>=10){ MouseMoveToLeftClick=0; SingleClick=false; } break; case 1: int PointTemp[2]; int Point[2]; if(SwitchCase==2){ std::cout<<"come SwitchCase2"<<std::endl; JudgementMouse(circles); break; } if(SingleClick==true && MouseMoveToLeftClick!=0){ std::cout<<"come LeftClick"<<std::endl; JudgementMouse(circles); MouseMoveToLeftClick=0; break; } if(circlesTemp->total==1 && circles->total==1){ float* p=(float*)cvGetSeqElem(circlesTemp,0); PointTemp[0]=cvRound(p[0]); PointTemp[1]=cvRound(p[1]); float* q=(float*)cvGetSeqElem(circles,0); Point[0]=cvRound(q[0]); Point[1]=cvRound(q[1]); } if(abs(Point[0]-PointTemp[0])<10 && abs(Point[1]-PointTemp[1])<10){ std::cout<<"come keyboard"<<std::endl; SwitchCase=1; keyboard.OutputKey(circles); break; }else if((abs(Point[0]-PointTemp[0])>10 || abs(Point[1]-PointTemp[1])>10)){ std::cout<<"come mouse"<<std::endl; SwitchCase=2; SingleClick=true; JudgementMouse(circles); break; } case 2: if(circlesTemp->total==1&& circles->total==2){ keyboard.OutputKey(circles); SwitchCase=3; break; }else{ JudgementMouse(circles); SwitchCase=4; break; } if(SwitchCase==3){ keyboard.OutputKey(circles); break; }else if (SwitchCase==4){ JudgementMouse(circles); break; } default: JudgementMouse(circles); SwitchTemp=0; SwitchCase=0; break; } circlesTemp=cvCloneSeq(circles,NULL); }
//functiown switch among mouse gesture and keyboard automatically void Recognition::FunctionSwitch(CvSeq* TouchBlobList){ /* Single key SwitchCase=1; MouseMove SwitchCase=2; Combination SwitchCase=3; TwoFingersMouse SwitchCase=4; ThreeFingerMouse SwitchCase=5; ThreeKeysCombination SwitchCase=6; */ //less fingers number's action can jump to more fingers numbers' action, but it can not jump back for(int i=0;i<TouchBlobList->total;i++){ float* p=(float*)cvGetSeqElem(TouchBlobList,i); if(cvRound(p[0])<65 || cvRound(p[0])>590 ||cvRound(p[1])<35||cvRound(p[1])>410){ MouseGestureSwitch(TouchBlobList); SwitchCounter=0; SwitchCase=0; return; } } SwitchCounter++;//the total number of how many frames come if(SwitchCounter==1){//initialize when first frame comes PreviousTouchBlobList=cvCloneSeq(TouchBlobList,NULL); } switch (TouchBlobList->total){//To switch among different numbers of circles case 0://if zero finger ,pass this to all functions and they will have corresponding actions gesture.estimation(TouchBlobList); MouseMoveToLeftClick++; keyboard.OutputKey(TouchBlobList); MouseGestureSwitch(TouchBlobList); SwitchCounter=0;//clear SwitchCase=0;//clear if(MouseMoveToLeftClick>5){//count for left click,the time between two left click should be limited MouseMoveToLeftClick=0; SingleClick=false;//forget last click,begin a new one } keyboard.UpKeys(); break; case 1: gesture.estimation(TouchBlobList);//for cross close window POINT PreviousPoint;//initilize a point for previousPoint object POINT Point;// initilize a point for current point object if(SwitchCase==2){//if previous action is mouse movement action MouseGestureSwitch(TouchBlobList); break; }else if(SingleClick==true && MouseMoveToLeftClick!=0){ MouseGestureSwitch(TouchBlobList); MouseMoveToLeftClick=0; keyboard.ClearVirtualKey(); break; //if none of these matches, evaluate for next use }else if(PreviousTouchBlobList->total==1 && TouchBlobList->total==1){ float* p=(float*)cvGetSeqElem(PreviousTouchBlobList,0); PreviousPoint.x=cvRound(p[0]); PreviousPoint.y=cvRound(p[1]); float* q=(float*)cvGetSeqElem(TouchBlobList,0); Point.x=cvRound(q[0]); Point.y=cvRound(q[1]); } // if(SwitchCase==0 || SwitchCase==1){ if(abs(Point.x-PreviousPoint.x)<10 && abs(Point.y-PreviousPoint.y)<10){ SwitchCase=1; keyboard.OutputKey(TouchBlobList); break; }else if((abs(Point.x-PreviousPoint.x)>10 || abs(Point.y-PreviousPoint.y)>10)){ SwitchCase=2; SingleClick=true; keyboard.ClearVirtualKey(); MouseGestureSwitch(TouchBlobList); break; } } break; case 2: if(SwitchCase==3){ keyboard.OutputKey(TouchBlobList); break; }else if (SwitchCase==4){ MouseGestureSwitch(TouchBlobList); break; } //in case previous action is not zero finger or one finger if(SwitchCase==0 || SwitchCase==1){ if(PreviousTouchBlobList->total==1 && TouchBlobList->total==2){ keyboard.OutputKey(TouchBlobList); SwitchCase=3; break; }else{ MouseGestureSwitch(TouchBlobList); SwitchCase=4; break; } } break; //three fingers action case 3: if(SwitchCase==6){ keyboard.OutputKey(TouchBlobList); break; }else if (SwitchCase==5){ MouseGestureSwitch(TouchBlobList); break; } // if(SwitchCase==0 || SwitchCase==3 || SwitchCase==4){ if(PreviousTouchBlobList->total==2&& TouchBlobList->total==3){ keyboard.OutputKey(TouchBlobList); SwitchCase=6; }else{ MouseGestureSwitch(TouchBlobList); SwitchCase=5; } } break; default://more then three fingers are all mouse actions MouseGestureSwitch(TouchBlobList);// only mouse & gestue has four fingers action SwitchCounter=0;//clean for next use SwitchCase=0;//clean for next use break; } PreviousTouchBlobList=cvCloneSeq(TouchBlobList,NULL);//copy current TouchBlobList to previous one }