基础介绍Opencv 里提取目标轮廓的函数是findContours,它的输入图像是一幅二值图像,输出的是每一个连通区域的轮廓点的集 合:vector<vector<Point>>。外层vector的size代表了图像中轮廓的个数,里面vector的 size代表了轮廓上点的个数。 轮廓进行填充的时候我会有下面2步骤: a)依次遍历轮廓点,将点绘制到img上 void drawMaxAreaLine(cv::Mat &dst, const std::vector<cv::Point> maxAreaPoints) { int step = dst.step; auto data = dst.data; for (int i = 0; i < maxAreaPoints.size(); ++i) { *(data + maxAreaPoints[i].x + maxAreaPoints[i].y * step) = 255; } } b)使用floodFill以及一个种子点进行填充 floodFill(savedGrayMat, Point(currentFrameEdge[0].x + 2, currentFrameEdge[0].y + 2), 255); 主要函数用法
cvFindContours(tour_buf,storage, &contour,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
输入图像image必须为一个2值单通道图像 contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示 hiararchy 参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。 mode表示轮廓的检索模式
method为轮廓的近似办法
正确调用查找函数后,接下来就是从轮廓序列contour(这里的contour不单单只有一个轮廓序列) 提取轮廓点了. contour可能是空指针,提取前最好判断一下 在提取之前还可以调用一个函数: #include "cv.h" #include #include #include #include #include #include #pragma comment(lib,"opencv_core2410d.lib") #pragma comment(lib,"opencv_highgui2410d.lib") #pragma comment(lib,"opencv_imgproc2410d.lib") using namespace std; typedef struct { CvPoint cP; int height; int width; } RecP; //自定义排序函数 namespace my { bool less(const RecP& s1, const RecP& s2) { //if(s1.cP.x < s2.cP.x && s1.cP.y < s2.cP.y) return s1.cP.x < s2.cP.x; //依次增大 } } void PrintVector( vector & vec) { for(vector::iterator n = vec.begin() ; n != vec.end() ; n++ ) { cout<< n->cP.x <<'\t'<< n->cP.y <<'\t'<< n->height<<'\t'<< n->width <<endl; } } IplImage* src; IplImage* img; IplImage* dst; IplImage* bianyuan; CvMemStorage* storage=NULL; int thresh=50; void on_trackbar(int pos) { CvSeq* contour=0; if(storage==NULL) { dst=cvCreateImage(cvGetSize(bianyuan), 8, 3); storage=cvCreateMemStorage(0); } else { cvClearMemStorage(storage); } cvSmooth(bianyuan, bianyuan, CV_GAUSSIAN, 3, 3, 0, 0); cvThreshold( bianyuan, img, thresh, 200, CV_THRESH_BINARY); cvNamedWindow( "threshold", 1); cvShowImage( "threshold", img ); cvFindContours(img, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); //查找轮廓 cvZero( dst ); //将数组中所有通道的所有元素的值都设置为0 vector vecP; int n=0; for( ; contour; contour = contour->h_next ) { CvRect rect=cvBoundingRect(contour,1); // 获取矩形边界框 if(abs(rect.width-rect.height)>3) { rect.width=0; rect.height=0; rect.x = rect.x + 640; rect.y = rect.y + 480; } CvPoint pt1=cvPoint(rect.x, rect.y), pt2=cvPoint(rect.x+rect.width, rect.y+rect.height); //定义矩形对顶点 cvRectangle(dst, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0); //绘制矩形边框 cvLine(dst, pt1, pt2, CV_RGB(0,255,0), 1, CV_AA, 0); //矩形对角线相连 pt1=cvPoint(rect.x, rect.y+rect.height), pt2=cvPoint(rect.x+rect.width, rect.y); cvLine(dst, pt1, pt2, CV_RGB(0,255,0), 1, CV_AA,0); //矩形对角线相连 RecP tmp; CvPoint p1; p1 = cvPoint(rect.x + rect.width/2, rect.y + rect.height/2); //矩形中心坐标 tmp.cP = p1; tmp.height = rect.height; tmp.width = rect.width; vecP.push_back(tmp); //printf("(%d,%d)\n", p1); sort(vecP.begin(), vecP.end(),my::less); //依次增大 //printf("(%d,%d):(%d,%d)\n", vecP[n].cP, vecP[n].height, vecP[n].width); n++; } PrintVector(vecP); cvShowImage( "Components", dst ); } int main() { const char* a = "Chess.jpg"; src = cvLoadImage(a, 0); cvSmooth(src,src,CV_GAUSSIAN,5,5,0,0); cvNamedWindow( "Source0000",1); cvShowImage( "Source0000", src); IplImage* bw =NULL; IplImage* color=NULL; IplImage* jh=NULL; IplImage* sm=NULL; if( !src ) return -1; jh = cvCreateImage( cvGetSize(src), 8, 1 ); sm = cvCreateImage( cvGetSize(src), 8, 1 ); bw = cvCreateImage( cvGetSize(src), 8, 1 ); color = cvCreateImage( cvGetSize(src), 8, 3 ); cvEqualizeHist( src, jh); cvSmooth(jh, sm, CV_MEDIAN, 3, 3, 0, 0); cvCanny(sm,bw,200,600,3); cvCvtColor( bw, color, CV_GRAY2BGR ); cvSaveImage("color.bmp",color); const char* b = "color.bmp"; bianyuan = cvLoadImage(b, 0); img=cvCreateImage(cvGetSize(bianyuan),8,1); cvNamedWindow( "Source",1); cvShowImage( "Source", bianyuan); cvNamedWindow( "Components",1); on_trackbar(0); cvWaitKey(0); cvDestroyWindow( "sorce" ); cvDestroyWindow( "threshold" ); cvDestroyWindow( "Components" ); cvReleaseImage( &src); cvReleaseImage( &img ); cvReleaseImage(&dst); cvReleaseMemStorage(&storage); return 0; } 实现效果
CV视觉网,转载请注明来源:CV视觉网 ? OpenCV 矩形轮廓检测 |
|