cvFindContours/findContours提取轮廓

来源:互联网 发布:js删除数组中指定对象 编辑:程序博客网 时间:2024/05/17 21:46

opencv在提取轮廓时,C/C++有两种方式,有些许不同,结合查找的资料和补充,做个小笔记;

功能,提取满足一定面积阈值和宽高比例的轮廓;

主函数

static int getContoursByC(char* Imgname, double minarea = 100, double whRatio = 1);static int getContoursByCplus(char* Imgname, double minarea=0, double whRatio=1);int main(){char* filename = new char[50];strcpy(filename, "../image/rl_4.jpg");getContoursByCplus(filename);delete[] filename;return 0;}

API实现

cvFindContours形式

/*采用cvFindContours提取轮廓,并过滤掉小面积轮廓,最后将轮廓保存*/static int getContoursByC(char* Imgname, double minarea, double whRatio){IplImage* src = cvLoadImage(Imgname, CV_LOAD_IMAGE_GRAYSCALE);if (!src){printf("read data error!\n");return -1;}IplImage* dst = cvCreateImage(cvGetSize(src), 8, 3);//the parm. for cvFindContoursCvMemStorage* storage = cvCreateMemStorage(0);CvSeq* contour = 0;double maxarea = 0;//for displaycvNamedWindow("Source", CV_WINDOW_NORMAL);cvShowImage("Source", src);//二值化cvThreshold(src, src, 120, 255, CV_THRESH_BINARY);//提取轮廓cvFindContours(src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);cvZero(dst);//清空数组/*CvSeq* _contour为了保存轮廓的首指针位置,因为随后contour将用来迭代*/CvSeq* _contour = contour;int maxAreaIdx = -1, iteratorIdx = 0;//n为面积最大轮廓索引,m为迭代索引for (int iteratorIdx = 0; contour != 0; contour = contour->h_next, iteratorIdx++/*更新迭代索引*/){double tmparea = fabs(cvContourArea(contour));if (tmparea > maxarea){maxarea = tmparea;maxAreaIdx = iteratorIdx;continue;}if (tmparea < minarea){//删除面积小于设定值的轮廓cvSeqRemove(contour, 0); continue;}CvRect aRect = cvBoundingRect(contour, 0);if ((aRect.width / aRect.height)<whRatio){//删除宽高比例小于设定值的轮廓cvSeqRemove(contour, 0); continue;}//CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );//创建一个色彩值//CvScalar color = CV_RGB(0, 255, 255);//max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。//如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。//如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。 //cvDrawContours(dst, contour, color, color, -1, 1, 8);//绘制外部和内部的轮廓}contour = _contour; /*int k=0;*///统计剩余轮廓,并画出最大面积的轮廓int count = 0;for (; contour != 0; contour = contour->h_next){count++;double tmparea = fabs(cvContourArea(contour));if (tmparea == maxarea /*k==n*/){CvScalar color = CV_RGB(255, 0, 0);cvDrawContours(dst, contour, color, color, -1, 1, 8);}/*k++;*/}printf("The total number of contours is:%d", count);cvNamedWindow("Components", CV_WINDOW_NORMAL);cvShowImage("Components", dst);cvSaveImage("dst.jpg", dst);//roateProcess(dst);cvWaitKey(0);//销毁窗口和图像存储cvDestroyWindow("Source");cvReleaseImage(&src);cvDestroyWindow("Components");cvReleaseImage(&dst);return 0;}

findContours形式

static int getContoursByCplus(char* Imgname, double minarea, double whRatio){cv::Mat src, dst, canny_output;/// Load source image and convert it to graysrc = imread(Imgname, 0);if (!src.data){std::cout << "read data error!" << std::endl;return -1;}blur(src, src, Size(3, 3));//the pram. for findContours,vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// Detect edges using cannyCanny(src, canny_output, 80, 255, 3);/// Find contoursfindContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLEdouble maxarea = 0;int maxAreaIdx = 0;for (int i = 0; i<contours.size(); i++){double tmparea = fabs(contourArea(contours[i]));if (tmparea>maxarea){maxarea = tmparea;maxAreaIdx = i;continue;}if (tmparea < minarea){//删除面积小于设定值的轮廓contours.erase(contours.begin() + i); std::wcout << "delete a small area" << std::endl;continue;}//计算轮廓的直径宽高Rect aRect =boundingRect(contours[i]);if ((aRect.width / aRect.height)<whRatio){//删除宽高比例小于设定值的轮廓contours.erase(contours.begin() + i); std::wcout << "delete a unnomalRatio area" << std::endl;continue;}}/// Draw contours,彩色轮廓dst= Mat::zeros(canny_output.size(), CV_8UC3);for (int i = 0; i< contours.size(); i++){//随机颜色Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(dst, contours, i, color, 2, 8, hierarchy, 0, Point());}// Create Windowchar* source_window = "countors";namedWindow(source_window, CV_WINDOW_NORMAL);imshow(source_window, dst);cv:; waitKey(0);return 0;}

之后


over!

4 0
原创粉丝点击