zoukankan      html  css  js  c++  java
  • OpenCV中的新函数connectedComponentsWithStats使用

    主要内容:对比新旧函数,用于过滤原始图像中轮廓分析后较小的区域,留下较大区域。
    关键字    :connectedComponentsWithStats

    在以前,常用的方法是是先调用 cv::findContours() 函数(传入cv::RETR_CCOMP 标志),随后在得到的连通区域上循环调用 cv::drawContours()
    比如,我在GOCVHelper中这样进行了实现
    //寻找最大的轮廓
        VP FindBigestContour(Mat src){    
            int imax = 0; //代表最大轮廓的序号
            int imaxcontour = -1; //代表最大轮廓的大小
            std::vector<std::vector<Point>>contours;    
            findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
            for (int i=0;i<contours.size();i++){
                int itmp =  contourArea(contours[i]);//这里采用的是轮廓大小
                if (imaxcontour < itmp ){
                    imax = i;
                    imaxcontour = itmp;
                }
            }
            return contours[imax];
        }
        //寻找并绘制出彩色联通区域
        vector<VPconnection2(Mat src,Matdraw){    
            draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
            vector<VP>contours;    
            findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
            //由于给大的区域着色会覆盖小的区域,所以首先进行排序操作
            //冒泡排序,由小到大排序
            VP vptmp;
            for(int i=1;i<contours.size();i++){
                for(int j=contours.size()-1;j>=i;j--){
                    if (contourArea(contours[j]) < contourArea(contours[j-1]))
                    {
                        vptmp = contours[j-1];
                        contours[j-1] = contours[j];
                        contours[j] = vptmp;
                    }
                }
            }
    在OpenCV3中有了新的专门的函数 cv::connectedComponents() 和函数 cv::connectedComponentsWithStats()
    定义:
    int  cv::connectedComponents (
        cv::InputArrayn image,                // input 8-bit single-channel (binary)
        cv::OutputArray labels,               // output label map
        int             connectivity = 8,     // 4- or 8-connected components
        int             ltype        = CV_32S // Output label type (CV_32S or CV_16U)
        );
    int  cv::connectedComponentsWithStats (
        cv::InputArrayn image,                // input 8-bit single-channel (binary)
        cv::OutputArray labels,               // output label map
        cv::OutputArray stats,                // Nx5 matrix (CV_32S) of statistics:
                                                              // [x0, y0, width0, height0, area0;
                                                              //  ... ; x(N-1), y(N-1), width(N-1),
                                                               // height(N-1), area(N-1)]
        cv::OutputArray centroids,            // Nx2 CV_64F matrix of centroids:
                                                               // [ cx0, cy0; ... ; cx(N-1), cy(N-1)]
        int             connectivity = 8,     // 4- or 8-connected components
        int             ltype        = CV_32S // Output label type (CV_32S or CV_16U)
        );
    其中,新出现的参数
    stats:长这样
    分别对应各个轮廓的x,y,width,height和面积。注意0的区域标识的是background
    centroids则对应的是中心点
    而label则对应于表示是当前像素是第几个轮廓
    例子:
    对于图像
         Mat img = cv::imread"e:/sandbox/rect.png",0); 
        cv::Mat  img_edgelabelsimg_colorstats,centroids;
        cv::threshold(imgimg_edge, 128, 255, cv::THRESH_BINARY);
        bitwise_not(img_edge,img_edge);
        cv::imshow("Image after threshold"img_edge);
        int inccomps = cv::connectedComponentsWithStats (
            img_edgelabels,
            statscentroids
            );
        cout << "Total Connected Components Detected: " << nccomps << endl;
        vector<cv::Vec3bcolors(nccomps+1);
        colors[0] = Vec3b(0,0,0); // background pixels remain black.
        fori = 1; i < nccompsi++ ) {
            colors[i] = Vec3b(rand()%256, rand()%256, rand()%256);
            ifstats.at<int>(icv::CC_STAT_AREA) < 200 )
                colors[i] = Vec3b(0,0,0); // small regions are painted with black too.
        }
        img_color = Mat::zeros(img.size(), CV_8UC3);
        forint y = 0; y < img_color.rowsy++ )
            forint x = 0; x < img_color.colsx++ )
            {
                int label = labels.at<int>(yx);
                CV_Assert(0 <= label && label <= nccomps);
                img_color.at<cv::Vec3b>(yx) = colors[label];
            }
        cv::imshow("Labeled map"img_color);
        cv::waitKey();
    注意:
    1、对于OpenCV来说,白色代表有数据,黑色代表没有数据,所以图像输入之前要转换成”黑底白图“
    2、看labels 和 stats,其中第1 2 6 个的面积小于200
    而labels中
    完全对的上号,结果






  • 相关阅读:
    使用envoy在k8s中作grpc的负载均衡
    操作系统中锁的原理(转)
    Linux shell利用sed如何批量更改文件名详解(转)
    Http 连接复用
    记一次Redis错误排查经历(redis cluster 节点重启后无限同步问题)
    nginx重启几种方法(转)
    k8s基础知识-1、基础组件
    Eclipse的预设的Include的路径
    转:音频与采样的计算
    转: wireshark过滤语法总结
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/7439655.html
Copyright © 2011-2022 走看看