//在图像srcImg上根据contour轮廓画上最小外接椭圆 CvBox2D DrawMinAreaEllipse(IplImage *srcImg,CvSeq *contour,CvScalar color/*=CV_RGB(255,0,0)*/) { int count = contour->total; // This is number point in contour CvPoint center; CvSize size; CvBox2D box; if( count < 6 ) return box; CvMat* points_f = cvCreateMat( 1, count, CV_32FC2 ); CvMat points_i = cvMat( 1, count, CV_32SC2, points_f->data.ptr ); cvCvtSeqToArray( contour, points_f->data.ptr, CV_WHOLE_SEQ ); cvConvert( &points_i, points_f ); // 椭圆拟合 box = cvFitEllipse2( points_f ); cout<<"拟合的椭圆参数:angle="<<box.angle<<",center=("<<box.center.x<<"," <<box.center.y<<")"<<",size(w,h)=("<<box.size.width<<","<<box.size.height<<")"<<endl; // 获得椭圆参数 center = cvPointFrom32f(box.center); size.width = cvRound(box.size.width*0.5)+1; size.height = cvRound(box.size.height*0.5)+1; // 画椭圆 cvEllipse(srcImg, center, size, -box.angle, 0, 360, color, 1, CV_AA, 0); cvReleaseMat(&points_f); return box; }
// Define trackbar callback functon. This function find contours, // draw it and approximate it by ellipses. void process_image(int h) { CvMemStorage* storage; CvSeq* contour; // Create dynamic structure and sequence. storage = cvCreateMemStorage(0); contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , storage); // Threshold the source image. This needful for cvFindContours(). cvThreshold( image03, image02, slider_pos, 255, CV_THRESH_BINARY ); // Find all contours. cvFindContours( image02, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); // Clear images. IPL use. cvZero(image02); cvZero(image04); // This cycle draw all contours and approximate it by ellipses. for(;contour;contour = contour->h_next) { int count = contour->total; // This is number point in contour CvPoint center; CvSize size; CvBox2D box; // Number point must be more than or equal to 6 (for cvFitEllipse_32f). if( count < 6 ) continue; CvMat* points_f = cvCreateMat( 1, count, CV_32FC2 ); CvMat points_i = cvMat( 1, count, CV_32SC2, points_f->data.ptr ); cvCvtSeqToArray( contour, points_f->data.ptr, CV_WHOLE_SEQ ); cvConvert( &points_i, points_f ); // Fits ellipse to current contour. box = cvFitEllipse2( points_f ); // Draw current contour. cvDrawContours(image04,contour,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1,8,cvPoint(0,0)); // Convert ellipse data from float to integer representation. center = cvPointFrom32f(box.center); size.width = cvRound(box.size.width*0.5); size.height = cvRound(box.size.height*0.5); // Draw ellipse. cvEllipse(image04, center, size, -box.angle, 0, 360, CV_RGB(0,0,255), 1, CV_AA, 0); cvReleaseMat(&points_f); } // Show image. HighGUI use. cvShowImage( "Result", image04 ); }
/* * PlatoFilter combines some of the other pre-defined filters to * determine if a given contour belongs to a plastic Dish */ int Contours::platoFilter(){ CvMemStorage* mem = cvCreateMemStorage(0); //Number of points should be at least 6. if(this->c->total<6) return false; CvBox2D box=cvMinAreaRect2(this->c,mem); CvBox2D box2=cvFitEllipse2(this->c); cvReleaseMemStorage(&mem); double majorAxis,minorAxis; double majorAxis2,minorAxis2; if(box2.size.width>box2.size.height){ majorAxis=box2.size.width; minorAxis=box2.size.height; }else{ minorAxis=box2.size.width; majorAxis=box2.size.height; } if(box.size.width>box.size.height){ majorAxis2=box.size.width; minorAxis2=box.size.height; }else{ minorAxis2=box.size.width; majorAxis2=box.size.height; } double boxDiff=fabs(majorAxis - majorAxis2) + fabs(minorAxis-minorAxis2); //eccentricity formula double ecc=sqrt(majorAxis*majorAxis -minorAxis*minorAxis)/majorAxis; double calcArea=miPI*(majorAxis/2)*(minorAxis/2); double realArea=this->getArea(); //Area of approximated elipse and of the contour should be similar. if(fabs(calcArea-realArea)/realArea > 0.2) return false; //gets circularity double circ=this->getCircularity(); if(circ<10 || circ>20) return false; if(ecc<0.65 || ecc>0.95) return false; return true; }
/** - FUNCTION: GetEllipse - FUNCTIONALITY: Calculates the ellipse that best fits the edges of the blob - PARAMETERS: - RESULT: - CvBox2D struct with the calculated ellipse - RESTRICTIONS: - AUTHOR: Ricard Borr� - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CvBox2D CBlob::GetEllipse() const { CvBox2D elipse; // necessitem 6 punts per calcular l'elipse if( edges != NULL && edges->total > 6) { elipse = cvFitEllipse2( edges ); } else { elipse.center.x = 0.0; elipse.center.y = 0.0; elipse.size.width = 0.0; elipse.size.height = 0.0; elipse.angle = 0.0; } return elipse; }
void defense::ImageToEllipseList(IplImage* TheInput,int PlaneNumber){ priority_queue<TheEllipse, vector<TheEllipse>,less<vector<TheEllipse>::value_type> > EllipQueue; TheTargetsEllipses.clear(); CvMemStorage* G_storage=NULL; G_storage=cvCreateMemStorage(0); CvSeq* contour = 0; IplImage * Maska; Maska = cvCreateImage( cvGetSize(TheInput),IPL_DEPTH_8U,1); int TotalEllip=0; for (int k=0;k<PlaneNumber;k++){ cvInRangeS(TheInput,cvScalarAll((k-1)*255/(float)PlaneNumber),cvScalarAll(k*255/(float)PlaneNumber),Maska); cvSmooth(Maska,Maska,CV_MEDIAN,3); int NC=cvFindContours( Maska, G_storage, &contour, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_L1 ); for( ; contour != 0; contour = contour->h_next ) { if ((contour->total > 10 )&&(TotalEllip<MaxEllip)){ CvMat* CountArray; CvBox2D Ellipdesc; CvPoint2D32f * OtroArray; OtroArray = new CvPoint2D32f[contour->total]; for(int q=0;q<contour->total;q++){ CvPoint* p = (CvPoint*)cvGetSeqElem( contour, q ); OtroArray[q].x = (float)p->x; OtroArray[q].y=(float)p->y; } CountArray=cvCreateMatHeader(contour->total,1,CV_32FC2); cvInitMatHeader(CountArray,contour->total,1,CV_32FC2,OtroArray); // calculating the best ellipse Ellipdesc=cvFitEllipse2(CountArray); EllipQueue.push(TheEllipse(Ellipdesc.center.x, Ellipdesc.center.y, Ellipdesc.size.width, Ellipdesc.size.height, Ellipdesc.angle, k*255/PlaneNumber)); TotalEllip++; delete [] OtroArray; cvReleaseMat(&CountArray); } // end of if contour-> total } // end of for contours } // end For the Planes while (!EllipQueue.empty()){ TheTargetsEllipses.push_back(EllipQueue.top()); EllipQueue.pop(); } cvReleaseImage(&Maska); // releasing mem storages if (contour!=NULL){cvClearSeq(contour);} //cvClearMemStorage(storage); if (G_storage!=NULL){cvReleaseMemStorage(&G_storage);} }
WSNATIVE_EXPORT bool ProcessFrame(IplImage * detection, IplImage * image, float m_GSD = 20, bgfg_cb_t bgfg_cb = 0) { //too few or too much detection? float mask_area = image->width*image->height; int width = image->width, height = image->width; float det_area = cvCountNonZero(detection); if (det_area < mask_area*0.00001 || det_area > mask_area*0.5 ) return false; CvMemStorage* storage, *storage1; storage = cvCreateMemStorage(0); storage1 = cvCreateMemStorage(0); CvSeq* contour; cvFindContours( detection, storage, &contour, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_NONE); CvRect rectBlob[MAXBLOBCNT]; CvBox2D rectBlob2D[MAXBLOBCNT]; int nBlobNum = 0; //note: this line erase all detected foreground pixels cvZero(detection); //go over all the blobs for( ; contour != 0; contour = contour->h_next ) { double fContourArea = fabs(cvContourArea(contour, CV_WHOLE_SEQ )); CvRect tmpRect = cvBoundingRect(contour, 1); float fRatio = 1.0*tmpRect.height/tmpRect.width; float occupy = fContourArea/(tmpRect.height*tmpRect.width); //TODO: make it an option cvDrawContours(detection,contour,CV_RGB(255,255,255),CV_RGB(255,255,255),0,CV_FILLED,8); //get the GSD(Ground Sampling Distance) for that location float GSD = 20; /* if (tmpRect.height/2.0 +tmpRect.y < m_Y1 ) GSD = m_GSD1; else if (tmpRect.height/2.0 +tmpRect.y > m_Y2 ) GSD = m_GSD2; else GSD = 1.0*m_GSD1*(m_Y2 - tmpRect.y - tmpRect.height/2.0 )/(m_Y2-m_Y1)+ 1.0*m_GSD2*(tmpRect.height/2.0 +tmpRect.y -m_Y1)/(m_Y2-m_Y1); */ CvRect tmpROI = cvBoundingRect( contour, 1); float boundary = 3; //pixels float min_area = GSD*GSD*0.10 /*0.25 for regular*/, max_area = width*height; if ( ( (tmpROI.x >= boundary && tmpROI.x+tmpROI.width <= width-boundary) || fContourArea > std::min<float>(1600.0 ,max_area/36) ) && fContourArea<max_area && fContourArea >= min_area && !( (occupy < 0.5 && fContourArea/(GSD*GSD) > 4.0 ) || occupy <0.33 ) && //TODO: make it adaptive? nBlobNum< MAXBLOBCNT) { rectBlob[nBlobNum] = tmpROI; CvBox2D box2d = cvFitEllipse2( contour); rectBlob2D[nBlobNum] = box2d; nBlobNum++; //draw outline //cvDrawContours(showimage,contour,CV_RGB(255,255,255),CV_RGB(255,255,255),1,1,8); } } for (int j = 0; j< nBlobNum; j++) { //get the attributes of each blob here if(bgfg_cb) { const CvRect& r = rectBlob[j]; bgfg_cb(r.x, r.y, r.width, r.height); } } cvReleaseMemStorage( &storage); cvReleaseMemStorage( &storage1); return true; }
void Gesture1::trackMarker (IplImage* destImg, CvPoint _r, CvPoint _b, CvPoint _g, CvPoint _y) { // find tissue box! CvPoint* objPoints = objectDetector->detect(destImg); // draw world->Step(1.0F/6.0F, 10, 10); cvLine(destImg, cvPoint(0,HEIGHT), cvPoint(1000,HEIGHT), CV_RGB(0,255,0), 3); for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { //printf("**draw body\n"); Box2DData* userData = (Box2DData*)b->GetUserData(); if (userData != NULL) { if (strcmp(userData->type, "Circle") == 0) { //b2Vec2 v = b->GetWorldCenter(); b2Vec2 v = b->GetPosition(); //printf("** x=%f y=%f r=%f\n", v.x, v.y, userData->radius); CvPoint center = cvPoint(v.x*WORLD_SCALE, v.y*WORLD_SCALE); cvCircle(destImg, center, userData->radius*WORLD_SCALE, CV_RGB(255,0,0), -1); } else if (strcmp(userData->type, "Box") == 0) { world->DestroyBody(b); } } } if (objPoints != NULL) { printf("construct body\n"); b2PolygonShape cs; b2Vec2 vertices[4] = { b2Vec2((float)(objPoints[0].x)/WORLD_SCALE, (float)(objPoints[0].y)/WORLD_SCALE), b2Vec2((float)(objPoints[1].x)/WORLD_SCALE, (float)(objPoints[1].y)/WORLD_SCALE), b2Vec2((float)(objPoints[2].x)/WORLD_SCALE, (float)(objPoints[2].y)/WORLD_SCALE), b2Vec2((float)(objPoints[3].x)/WORLD_SCALE, (float)(objPoints[3].y)/WORLD_SCALE) }; cs.Set(vertices, 4); b2BodyDef bd; //bd.type = b2_staticBody; Box2DData* obj = new Box2DData(); strcpy(obj->type, "Box"); bd.userData = obj; b2Body* body1 = world->CreateBody(&bd); body1->CreateFixture(&cs, 0.0f); } if (_r.x < 0) return; Point2D r = toPoint2D(_r); // if marker is not moving for a while, reset the path int len = path.size(); if (len > KEEP_MAX) { path.erase(path.begin()); } int nearCount = 0; int actual = min(KEEP_COUNT, len); /* for(int i=0; i<actual; i++){ Point2D p = path[len-1-i]; double d = dist(p, r); //printf("dist=%f\n", d); if (d < NEAR_THRESHOLD) ++nearCount; } if (nearCount > (double)actual * DONT_MOVE_THRESHOLD_RATE) { // marker is not moving, so clear the path printf("cleared\n"); path.clear(); } */ path.push_back(r); // decide if we should recognize time_t current; time(¤t); double interval = difftime(current, lastTime); printf("interval=%f\n", interval); if (interval < INTERVAL_SEC) return; len = path.size(); if (len < 5) return; RecognitionResult res = g.recognize(path); printf("%s:%f\n", res.name.c_str(), res.score); if (res.name == "Circle" && res.score > SCORE_THRESHOLD) { printf("##circle detect##\n"); // convert to vector<Point2D> to CvSeq<CvPoint> CvSeqWriter writer; CvMemStorage* storage = cvCreateMemStorage(0); cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer); for (int i=0; i<len; i++) { CvPoint pt = toCvPoint(path[i]); CV_WRITE_SEQ_ELEM(pt, writer); } CvSeq* seq = cvEndWriteSeq(&writer); CvBox2D ellipse = cvFitEllipse2(seq); float radius = std::min(ellipse.size.width, ellipse.size.height)/(4.0F*WORLD_SCALE); cvEllipseBox(destImg, ellipse, CV_RGB(0,255,255), -1); // add Box2D object { b2CircleShape cs; cs.m_radius = radius; printf(" x=%f y=%f radius:%f\n", ellipse.center.x/WORLD_SCALE, ellipse.center.y/WORLD_SCALE, radius); b2BodyDef bd; bd.type = b2_dynamicBody; bd.position.Set(ellipse.center.x/WORLD_SCALE, ellipse.center.y/WORLD_SCALE); Box2DData* obj = new Box2DData(); strcpy(obj->type, "Circle"); obj->radius = radius; bd.userData = obj; b2Body* body1 = world->CreateBody(&bd); b2FixtureDef fixtureDef; fixtureDef.shape = &cs; fixtureDef.density = 1.0f; fixtureDef.friction = 0.3f; fixtureDef.restitution = 0.6f; body1->CreateFixture(&fixtureDef); } time(&lastTime); //cvEllipseBox(destImg, ellipse, CV_RGB(125,125,255)); } }
void cvFitEllipse( const CvPoint2D32f* points, int count, CvBox2D* box ) { CvMat mat = cvMat( 1, count, CV_32FC2, (void*)points ); *box = cvFitEllipse2( &mat ); }
int main( int argc, char** argv ) { char path[1024]; IplImage* img; help(); if (argc!=2) { strcpy(path,"puzzle.png"); img = cvLoadImage( path, CV_LOAD_IMAGE_GRAYSCALE ); if (!img) { printf("\nUsage: mser_sample <path_to_image>\n"); return 0; } } else { strcpy(path,argv[1]); img = cvLoadImage( path, CV_LOAD_IMAGE_GRAYSCALE ); } if (!img) { printf("Unable to load image %s\n",path); return 0; } IplImage* rsp = cvLoadImage( path, CV_LOAD_IMAGE_COLOR ); IplImage* ellipses = cvCloneImage(rsp); cvCvtColor(img,ellipses,CV_GRAY2BGR); CvSeq* contours; CvMemStorage* storage= cvCreateMemStorage(); IplImage* hsv = cvCreateImage( cvGetSize( rsp ), IPL_DEPTH_8U, 3 ); cvCvtColor( rsp, hsv, CV_BGR2YCrCb ); CvMSERParams params = cvMSERParams();//cvMSERParams( 5, 60, cvRound(.2*img->width*img->height), .25, .2 ); double t = (double)cvGetTickCount(); cvExtractMSER( hsv, NULL, &contours, storage, params ); t = cvGetTickCount() - t; printf( "MSER extracted %d contours in %g ms.\n", contours->total, t/((double)cvGetTickFrequency()*1000.) ); uchar* rsptr = (uchar*)rsp->imageData; // draw mser with different color for ( int i = contours->total-1; i >= 0; i-- ) { CvSeq* r = *(CvSeq**)cvGetSeqElem( contours, i ); for ( int j = 0; j < r->total; j++ ) { CvPoint* pt = CV_GET_SEQ_ELEM( CvPoint, r, j ); rsptr[pt->x*3+pt->y*rsp->widthStep] = bcolors[i%9][2]; rsptr[pt->x*3+1+pt->y*rsp->widthStep] = bcolors[i%9][1]; rsptr[pt->x*3+2+pt->y*rsp->widthStep] = bcolors[i%9][0]; } } // find ellipse ( it seems cvfitellipse2 have error or sth? for ( int i = 0; i < contours->total; i++ ) { CvContour* r = *(CvContour**)cvGetSeqElem( contours, i ); CvBox2D box = cvFitEllipse2( r ); box.angle=(float)CV_PI/2-box.angle; if ( r->color > 0 ) cvEllipseBox( ellipses, box, colors[9], 2 ); else cvEllipseBox( ellipses, box, colors[2], 2 ); } cvSaveImage( "rsp.png", rsp ); cvNamedWindow( "original", 0 ); cvShowImage( "original", img ); cvNamedWindow( "response", 0 ); cvShowImage( "response", rsp ); cvNamedWindow( "ellipses", 0 ); cvShowImage( "ellipses", ellipses ); cvWaitKey(0); cvDestroyWindow( "original" ); cvDestroyWindow( "response" ); cvDestroyWindow( "ellipses" ); cvReleaseImage(&rsp); cvReleaseImage(&img); cvReleaseImage(&ellipses); }