【opencv学习之三十二】轮廓查找并统计2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abcvincent/article/details/79274468

关于opencv在图像中查找轮廓并统计的方法基本这样几个步骤:1、读取图像——2、前期处理滤波平滑等——3、分割图像,一般阈值分割——4、FindContours查找轮廓——5、统计轮廓——6、根据连通域面积大小过滤轮廓——7、染色需要显示的轮廓——8、显示图像;上个数米的程序例子是用opencv2写的,很多方法都带cv前缀,下面用opencv3进行轮廓查找并统计:

void imgContours()//轮廓查找并统计
{
    //1、读取图像
    Mat img=imread("D:/ImageTest/22.PNG");//加载图片
    Mat dst;
    //2、前期处理滤波平衡等
    cv::cvtColor(img,img,COLOR_RGB2GRAY);//进行,灰度处理
    //3、分割图像,一般阈值分割
    threshold( img,                 //输入图像,原始数组 (单通道 , 8-bit of 32-bit 浮点数).
               dst,                          //输出图像,输出数组,必须与 src 的类型一致,或者为 8-bit.
               100,                           //分割值
               255,                         // 使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
               THRESH_BINARY_INV ); //阈值类型,opencv认为白色部分为被分割出来的部分
    //4、FindContours查找轮廓
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    //    findContours(dst,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_NONE,Point());//最外层轮廓
    findContours(dst,contours,hierarchy,RETR_CCOMP, CHAIN_APPROX_SIMPLE,Point());//所有轮廓CV_CHAIN_APPROX_SIMPLE
    //    findContours返回为vector<vector<Point> >的轮廓向量
    //染色需要显示的轮廓
    Mat dst1 = Mat::zeros(img.size(), CV_8UC3);//初始化dst
    if( !contours.empty() && !hierarchy.empty() ) //开始处理
    {
        //遍历所有顶层轮廓,随机生成颜色值绘制给各连接组成部分
        for(  int idx = 0; idx >= 0; idx = hierarchy[idx][0] )
        {
            Scalar color( (rand()&255), (rand()&255), (rand()&255) );//随机产生颜色 rand()产生随机数
            //绘制填充轮廓
            drawContours(
                        dst1,                    //用来绘制轮廓的图像
                        contours,         //指向第一个轮廓的指针
                        idx,                   //
                        color,               //内层轮廓的颜色
                        CV_FILLED,     //绘制轮廓的最大等级,绘制轮廓时所使用的线条的粗细度。如果值为负(e.g. =CV_FILLED),绘制内层轮廓。
                        8,                     //线条的类型
                        hierarchy );    //按照给出的偏移量移动每一个轮廓点坐标.
        }
    }
    //    imshow("srcImg", img);
    //    imshow("findcontours",dst1);
    //    waitKey(0);
    
    //6、统计轮廓
    //统计面积
    double  contour_area_tmp=0;
    double  contour_area_max=0;
    double  contour_area_min=0;
    double  contour_area_sum=0;
    for (int i = 0; i<contours.size(); i++)
    {
        contour_area_tmp=fabs(contourArea(contours[i]));
        if( contour_area_tmp > contour_area_max )
        {
            contour_area_max = contour_area_tmp; //找到面积最大的轮廓
        }
        contour_area_sum += contour_area_tmp; //求所有轮廓的面积和
    }
    contour_area_min=contour_area_max;
    for (int i = 0; i<contours.size(); i++)
    {
        contour_area_tmp=fabs(contourArea(contours[i]));
        if( contour_area_tmp< contour_area_min )
        {
            contour_area_min = contour_area_tmp; //找到面积最小的轮廓
        }
    }
    double  contour_area_ave = contour_area_sum/ (contours.size()+1); //求出所有轮廓的平均值
    qDebug()<<"面积最大值:"<<contour_area_max;//输出计时
    qDebug()<<"面积最小值:"<<contour_area_min;//输出计时
    qDebug()<<"对象数量:"<<contours.size()+1;//输出计时
    qDebug()<<"面积总和:"<<contour_area_sum;//输出计时
    qDebug()<<"面积平均值:"<<contour_area_ave;//输出计时
    for (int i = 0; i<contours.size(); i++)
    {
        contour_area_tmp=fabs(contourArea(contours[i]));
        qDebug()<<"所有面积值:"<<i<<":"<<QString::number(contour_area_tmp,10,2);//输出计时
    }
    qDebug()<<"///////////////////////";//输出
    
   //7、根据连通域面积大小对轮廓进行排序
    vector<double>  contoursGram;
    for (int i = 0; i<contours.size(); i++)
    {
        contoursGram.push_back(fabs(contourArea(contours[i])));
        //        qDebug()<<"所有面积值:"<<i<<":"<<QString::number( contoursGram[i],10,2);//输出计时
    }
    sort( contoursGram.begin(), contoursGram.end());//sort函数排序

    for (int i = 0; i< contoursGram.size(); i++)
    {
        qDebug()<<"所有面积值:"<<i<<":"<<QString::number( contoursGram[i],10,2);//输出计时
    }

    //8、显示图像;
    //    //添加文字
    QString strg1=QString::number(contour_area_max,10,3);
    QString str1=QString("contour_area_max:%1").arg(strg1);
    QByteArray cStr1 = str1.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p1 = cStr1.data();
    putText(dst1,p1, Point(30, 30),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    QString strg2=QString::number(contour_area_min,10,3);
    QString str2=QString("contour_area_min:%1").arg(strg2);
    QByteArray cStr2 = str2.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p2 = cStr2.data();
    putText(dst1,p2, Point(30, 30*2),CV_FONT_HERSHEY_COMPLEX,0.8, Scalar(0, 0, 255), 1, 8);

    QString strg3=QString::number(contours.size()+1,10,3);
    QString str3=QString("contours.size:%1").arg(strg3);
    QByteArray cStr3 = str3.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p3 = cStr3.data();
    putText(dst1,p3, Point(30, 30*3),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    QString strg4=QString::number(contour_area_sum,10,3);
    QString str4=QString("contour_area_sum:%1").arg(strg4);
    QByteArray cStr4 = str4.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p4 = cStr4.data();
    putText(dst1,p4, Point(30, 30*4),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);


    QString strg5=QString::number(contour_area_ave,10,3);
    QString str5=QString("contour_area_ave:%1").arg(strg5);
    QByteArray cStr5 = str5.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p5 = cStr5.data();
    putText(dst1,p5, Point(30, 30*5),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    imshow("srcImg", img);
    imshow("findcontours",dst1);
    waitKey(0);
}
效果:




猜你喜欢

转载自blog.csdn.net/abcvincent/article/details/79274468