CvContourPolygon *cvSimplifyPolygon(CvContourPolygon const *p, double const delta) { CV_FUNCNAME("cvSimplifyPolygon"); __CV_BEGIN__; { CV_ASSERT(p!=NULL); CV_ASSERT(p->size()>2); double furtherDistance=0.; unsigned int furtherIndex=0; CvContourPolygon::const_iterator it=p->begin(); ++it; for (unsigned int i=1; it!=p->end(); ++it, i++) { double d = cvDistancePointPoint(*it, p->front()); if (d>furtherDistance) { furtherDistance = d; furtherIndex = i; } } if (furtherDistance<delta) { CvContourPolygon *result = new CvContourPolygon; result->push_back(p->front()); return result; } bool *pnUseFlag = new bool[p->size()]; for (int i=1; i<p->size(); i++) pnUseFlag[i] = false; pnUseFlag[0] = pnUseFlag[furtherIndex] = true; simplifyPolygonRecursive(p, 0, furtherIndex, pnUseFlag, delta); simplifyPolygonRecursive(p, furtherIndex, -1, pnUseFlag, delta); CvContourPolygon *result = new CvContourPolygon; for (int i=0; i<p->size(); i++) if (pnUseFlag[i]) result->push_back((*p)[i]); delete[] pnUseFlag; return result; } __CV_END__; }
CvContourPolygon *cvConvertChainCodesToPolygon(CvContourChainCode const *cc) { CV_FUNCNAME("cvConvertChainCodesToPolygon"); __CV_BEGIN__; { CV_ASSERT(cc!=NULL); CvContourPolygon *contour = new CvContourPolygon; unsigned int x = cc->startingPoint.x; unsigned int y = cc->startingPoint.y; contour->push_back(cvPoint(x, y)); if (cc->chainCode.size()) { CvChainCodes::const_iterator it=cc->chainCode.begin(); CvChainCode lastCode = *it; x += cvChainCodeMoves[*it][0]; y += cvChainCodeMoves[*it][1]; ++it; for (; it!=cc->chainCode.end(); ++it) { if (lastCode!=*it) { contour->push_back(cvPoint(x, y)); lastCode=*it; } x += cvChainCodeMoves[*it][0]; y += cvChainCodeMoves[*it][1]; } } return contour; } __CV_END__; }
void cvWriteContourPolygonSVG(const CvContourPolygon& p, const string& filename, const CvScalar& stroke, const CvScalar& fill) { int minx=INT_MAX; int miny=INT_MAX; int maxx=INT_MIN; int maxy=INT_MIN; stringstream buffer(""); for (CvContourPolygon::const_iterator it=p.begin(); it!=p.end(); ++it) { if (it->x>maxx) maxx = it->x; if (it->x<minx) minx = it->x; if (it->y>maxy) maxy = it->y; if (it->y<miny) miny = it->y; buffer << it->x << "," << it->y << " "; } ofstream f; f.open(filename.c_str()); f << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << endl; f << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">" << endl; f << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" width=\"" << maxx-minx << "px\" height=\"" << maxy-miny << "px\" viewBox=\"" << minx << " " << miny << " " << maxx << " " << maxy << "\" zoomAndPan=\"disable\" >" << endl; f << "<polygon fill=\"rgb(" << fill.val[0] << "," << fill.val[1] << "," << fill.val[2] << ")\" stroke=\"rgb(" << stroke.val[0] << "," << stroke.val[1] << "," << stroke.val[2] << ")\" stroke-width=\"1\" points=\"" << buffer.str() << "\"/>" << endl; f << "</svg>" << endl; f.close(); }
int main(int argc, char** argv) { CvTracks tracks; /*drawing*/ CvPoint pt3; /*colors*/ CvScalar green = CV_RGB(0,255,0); cvNamedWindow("red_object_tracking", CV_WINDOW_AUTOSIZE); CvCapture* capture; capture = cvCreateFileCapture (argv[1]); assert( capture != NULL ); IplImage *img = cvQueryFrame( capture ); CvSize imgSize = cvGetSize(img); IplImage *frame = cvCreateImage(cvGetSize(img), img->depth, img->nChannels); IplConvKernel* morphKernel = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT, NULL); //unsigned int frameNumber = 0; unsigned int blobNumber = 0; bool quit = false; while (!quit) { IplImage *img = cvQueryFrame( capture ); cvConvertScale(img, frame, 1, 0); IplImage *segmentated = cvCreateImage(imgSize, 8, 1); // Detecting red pixels: // (This is very slow, use direct access better...) for (unsigned int j=0; j<imgSize.height; j++) for (unsigned int i=0; i<imgSize.width; i++) { CvScalar c = cvGet2D(frame, j, i); double b = ((double)c.val[0])/255.; double g = ((double)c.val[1])/255.; double r = ((double)c.val[2])/255.; unsigned char f = 255*((r<0.15)&&(b<0.15)&&(g<0.15)); //unsigned char f = 255*((r>0.5+g)&&(r>0.5+b)); cvSet2D(segmentated, j, i, CV_RGB(f, f, f)); } cvMorphologyEx(segmentated, segmentated, NULL, morphKernel, CV_MOP_OPEN, 1); cvShowImage("segmentated", segmentated); IplImage *labelImg = cvCreateImage(cvGetSize(frame), IPL_DEPTH_LABEL, 1); CvBlobs blobs; unsigned int result = cvLabel(segmentated, labelImg, blobs); cvFilterByArea(blobs, 50, (frame->width*frame->height)/30); //cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_BOUNDING_BOX); //cvUpdateTracks(blobs, tracks, 200., 5); //cvRenderTracks(tracks, frame, frame, CV_TRACK_RENDER_ID|CV_TRACK_RENDER_BOUNDING_BOX); int l = 0; for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it, l++) { //define marker corners pt3 = cvPoint(it->second->centroid.x,it->second->centroid.y); // draw small corner circle cvCircle(frame, pt3, 3, green, 1, 8, 0); CvContourPolygon *polygon = cvConvertChainCodesToPolygon(&(*it).second->contour); double perimeter = cvContourPolygonPerimeter(polygon); CvContourPolygon *sPolygon = cvSimplifyPolygon(polygon, 5. ); CvContourPolygon *cPolygon = cvPolygonContourConvexHull(sPolygon); if (1) // if (sPolygon->size()==4) { for (CvContourPolygon::const_iterator itp=sPolygon->begin(); itp!=sPolygon->end(); ++itp) { int x = itp->x; int y = itp->y; CvPoint pt1 = cvPoint(x,y); cvCircle(frame, pt1, 3, CV_RGB(255, 128, 50), 1, 8, 0); cvRenderContourPolygon(sPolygon, frame, CV_RGB(0, 0, 255)); } } //cvRenderContourChainCode(&(*it).second->contour, frame); //cvRenderContourPolygon(sPolygon, frame, CV_RGB(0, 0, 255)); //cvRenderContourPolygon(cPolygon, frame, CV_RGB(0, 255, 0)); } cvNamedWindow("red_object_tracking", CV_WINDOW_NORMAL) ; cvShowImage("red_object_tracking", frame); /*std::stringstream filename; filename << "redobject_" << std::setw(5) << std::setfill('0') << frameNumber << ".png"; cvSaveImage(filename.str().c_str(), frame);*/ cvReleaseImage(&labelImg); cvReleaseImage(&segmentated); char k = cvWaitKey(0)&0xff; switch (k) { case 27: case 'q': case 'Q': quit = true; break; case 's': case 'S': for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it) { std::stringstream filename; filename << "redobject_blob_" << std::setw(5) << std::setfill('0') << blobNumber << ".png"; cvSaveImageBlob(filename.str().c_str(), img, it->second); blobNumber++; std::cout << filename.str() << " saved!" << std::endl; } break; } for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it) { std::cout << "Blob #" << it->second->label << ": Area=" << it->second->area << ", Centroid=(" << it->second->centroid.x << ", " << it->second->centroid.y << ")" << std::endl; } cvReleaseBlobs(blobs); //frameNumber++; } cvReleaseStructuringElement(&morphKernel); cvReleaseImage(&frame); cvDestroyWindow("red_object_tracking"); return 0; }