【2】 去除面积较小的连通域

来源:互联网 发布:adobe通用破解补丁mac 编辑:程序博客网 时间:2024/06/05 09:00

在去除面积较小的轮廓上,这里介绍两种方法 。


第一种方法是将满足条件的轮廓存入vector,然后再画出这个vector中的轮廓。

另一种方法是只绘出符合条件的轮廓。


在效率上,后者直接绘出,不需要前者的装入vector操作,因此,后者相对要快很多。


//------------------------------------【头文件、命名空间】-----------------------------------//        描述:包含程序所依赖的头文件和命名空间//-------------------------------------------------------------------------------------------#include  <opencv2/opencv.hpp>#include  <opencv2/imgproc/imgproc.hpp> #include  <opencv2/highgui/highgui.hpp> #include  <iostream>#include  <fstream>#include  <time.h>#include  <math.h>using namespace cv;using namespace std;//------------------------------------【主函数】----------------------------------------------//         描述:完成去除二值化图像中面积较小的连通域//--------------------------------------------------------------------------------------------int main() {clock_t start,end ,start1,end1 ,start2,end2,start20,end20,start3,end3;start=clock();Mat srcIm,grayIm,adthreshIm;//adaptive中的可调参数double MaxV=255;//给像素赋的满足条件的非零值(最大值)int blockSize=7;//计算阈值的像素领域的大小,取3,5,7等double C=20;//减去平均值或加权平均值后的常数值srcIm=imread("sample.jpg",1 );if (!srcIm.data) { printf("读取失败"); return false;}cvtColor(srcIm,grayIm,COLOR_RGB2GRAY);//imshow("GrayImage",grayIm);//自适应阈值化adaptiveThreshold(grayIm,adthreshIm,MaxV, ADAPTIVE_THRESH_MEAN_C,//先求出块中的均值,在减掉C //ADAPTIVE_THRESH_GAUSSIAN_C , //高斯先求出块中的加权和,再减掉C THRESH_BINARY_INV,blockSize,C);//imshow("AdaptiveThreshImage",adthreshIm);//................................轮廓........................................... //Mat element=getStructuringElement(MORPH_RECT,Size(3,3)); //定义核 //morphologyEx(adthreshIm,adthreshIm,MORPH_OPEN,element);//开运算 //morphologyEx(adthreshIm,adthreshIm,MORPH_CLOSE,element);//闭运算double min_area=2000;   //轮廓较小面积double length=80;      //轮廓长度double min_circlearea=400;//面积为0的轮廓的外接圆面积 //获取轮廓vector<vector<Point>> contours, cont;  vector<Vec4i> hierarchy;findContours(adthreshIm, contours,                hierarchy,CV_RETR_CCOMP,            //轮廓树//CV_RETR_EXTERNAL,       //外围轮廓CV_CHAIN_APPROX_NONE );   //获取全部轮廓     //绘出轮廓Mat drawCont(adthreshIm.size() , CV_8U ,Scalar(255)) ;drawContours(drawCont,contours,-1,Scalar(0) ,-1) ; imshow("轮廓",drawCont);cout<<"轮廓总条数:"<<contours.size()<<"\n"<<endl;//.......................................方法(1).....................................//    描述:利用一个新的vector<vector<Point>>,去装符合要求的轮廓//.....................................................................................//提取符合要求的轮廓start1=clock();Mat drawCont1(adthreshIm.size() , CV_8U ,Scalar(255)) ;for (int i = 0; i >= 0; i = hierarchy[i][0]){if ( contourArea(contours[i]) > min_area )cont.push_back( contours[i] );}//画出符合要求的轮廓并保存for(int j = 0;j < cont.size(); j++){drawContours(drawCont1,cont,-1,Scalar(0),-1);}end1=clock();cout<<"Run time a: "<<(double)(end1 - start1) / CLOCKS_PER_SEC<<"S"<< endl;imshow("轮廓a",drawCont1);//imwrite("a.jpg",drawCont1);cout<<"轮廓a条数:"<<cont.size()<<endl;cout<<"drawCont1非零像素点数:"<<countNonZero(drawCont1)<<"\n"<<endl;//....................................方法(2)..........................................//    描述:只绘出符合要求的轮廓//.......................................................................................//- - - - - - - - - - - - - - - - - - 利用轮廓长度- -  - - - - - - - - - - - - - - - - - -  start2=clock();Mat drawCont2(adthreshIm.size() , CV_8U ,Scalar(255)) ;for(int i = 0;i < contours.size();i++){if( contourArea(contours[i]) > min_area ){drawContours(drawCont2,contours,i,Scalar(0),CV_FILLED);}}end2=clock();cout<<"Run time b: "<<(double)(end2 - start2) / CLOCKS_PER_SEC<<"S"<<endl;imshow("轮廓b",drawCont2);//imwrite("b.jpg",drawCont2);cout<<"轮廓b条数:"<<contours.size()<<endl;cout<<"drawCont2非零像素点数:"<<countNonZero(drawCont2)<<"\n"<<endl;       waitKey(0);    return 0; }


当然,在提到vector时(vector<vector<Point>>),可以考虑迭代器。至于迭代器的方法,将在下一篇介绍(下一篇要保留的除了面积大的轮廓外,还有面积为零,但很长的轮廓)。







0 0
原创粉丝点击