美文网首页文史赏析古今中外
C#:轮廓发现与轮廓分析

C#:轮廓发现与轮廓分析

作者: 大龙10 | 来源:发表于2023-09-15 11:10 被阅读0次

    一、二值图像分析

    • 二值图像分析最常见的一个主要方式就是轮廓发现与轮廓分析
      其中轮廓发现的目的是为轮廓分析做准备,
      经过轮廓分析我们可以得到轮廓各种有用的属性信息。

    二、边缘检测和轮廓检测的区别

    • 边缘检测
      主要是通过一些手段检测数字图像中明暗变化剧烈(即梯度变化比较大)像素点,偏向于图像中像素点的变化。如canny边缘检测,结果通常保存在和源图片一样尺寸和类型的边缘图中。
    • 轮廓检测
      指检测图像中的对象边界,更偏向于关注上层语义对象。
      如OpenCV中的findContours()函数, 它会得到每一个轮廓并以点向量方式存储,除此也得到一个图像的拓扑信息,即一个轮廓的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的索引编号。

    三、轮廓发现与绘制

    • 在OpenCV里面利用findContours()函数和drawContours()函数实现这一功能。
    void FindContours(InputOutputArray image, 
      out Point[][] contours, 
      out HierarchyIndex[] hierarchy, 
      RetrievalModes mode, 
      ContourApproximationModes method, 
      Point? offset = null);
    
    • FindContours
      • 参数一: image,输入图像、八位单通道的,背景为黑色的二值图像。(一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像)

      • 参数二:contours,输出轮廓图像。是一个向量,向量的每个元素都是一个轮廓。因此,这个向量的每个元素仍是一个向量。即:

           vector<vector<Point> > contours;
        
      • 参数三:hierarchy,输出各个轮廓的继承关系。hierarchy也是一个向量,长度和contours相等,每个元素和contours的元素对应。hierarchy的每个元素是一个包含四个整型数的向量。即:

           vector<Vec4i> hierarchy;
        
      • 参数四:mode,检测轮廓的方法。有四种方法:
        RETR_EXTERNAL:只检测外轮廓。忽略轮廓内部的洞。
        RETR_LIST:检测所有轮廓,但不建立继承(包含)关系。
        RETR_TREE:检测所有轮廓,并且建立所有的继承(包含)关系。
        RETR_CCOMP:检测所有轮廓,但是仅仅建立两层包含关系。

      • 参数五:method,每个轮廓的编码信息。也有四种(常用前两种)
        CHAIN_APPROX_NONE:把轮廓上所有的点存储。
        CHAIN_APPROX_SIMPLE:只存储轮廓上的拐点。
        CHAIN_APPROX_TC89_L1,CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

      • 参数六: Point,偏移量。默认为0
        注意:该函数将白色区域当作前景物体。所以findContours()函数是黑色背景下找白色轮廓。

    void DrawContours(InputOutputArray image, 
       IEnumerable<IEnumerable<Point>> contours,
       int contourIdx, Scalar color, 
       int thickness = 1,
       LineTypes lineType = LineTypes.Link8, 
       IEnumerable<HierarchyIndex> hierarchy = null, 
       int maxLevel = int.MaxValue, 
       Point? offset = null);
    
    • DrawContours()函数
      • contours 全部发现的轮廓对象
      • contourIdx 轮廓索引号,-1表示绘制所有轮廓
      • MaxValue最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓
      • Point? offset 轮廓位移,可选

    四、轮廓分析(二值图像分析)

    • 在得到图像的轮廓以后,我们就可以进行轮廓分析。
      经过轮廓分析我们可以得到轮廓各种有用的属性信息、常见的如下:
      • 1、轮廓的矩
      • 2、轮廓的面积
      • 3、轮廓的长度
      • 4、轮廓的近似多边形
      • 5、轮廓的凸包
      • 6、轮廓的直边界矩形
      • 7、轮廓的旋转矩形
      • 8、轮廓的最小外包圆
      • 9、轮廓的拟合椭圆
      • 10、轮廓的拟合直线
      • 11、轮廓的最小外包三角形

    五、程序

            private void uiButton7_Click(object sender, EventArgs e)
            {
                Mat result = src_img.Clone();
                Mat m7 = new Mat();
                double threshold1 = 10;
                double threshold2 = 200;
                int select_i = 0;
                Cv2.Canny(dst, m7, threshold1, threshold2);
                OpenCvSharp.Point[][] contours; //vector<vector<Point>> contours;
                HierarchyIndex[] hierarchyIndexes; //vector<Vec4i> hierarchy;
     
                Cv2.FindContours(m7, out contours, out hierarchyIndexes, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
    
                for (int i = 0; i < contours.Length; i++)
                {
                    double length = Cv2.ArcLength(contours[i], true);
                    if (length >= 500)
                    {
                        select_i = i;
                        Cv2.DrawContours(result, contours, i, new Scalar(0, 255, 255), 2);
    
                        Cv2.PutText(result, "i=" + i.ToString(), new OpenCvSharp.Point(20, 120), OpenCvSharp.HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 255));
                        double area = Cv2.ContourArea(contours[i], false);
                        Cv2.PutText(result, "length=" + length.ToString(), new OpenCvSharp.Point(20, 160), OpenCvSharp.HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 255));
    
                        Cv2.PutText(result, "area=" + area.ToString(), new OpenCvSharp.Point(20, 200), OpenCvSharp.HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 255));
                        RotatedRect rect=Cv2.MinAreaRect(contours[0]);
    
                        Cv2.Rectangle(result, rect.BoundingRect(), new Scalar(0, 0, 255), 2, LineTypes.Link8,0);
                        Cv2.PutText(result, "width=" + rect.Size.Width.ToString(), new OpenCvSharp.Point(20, 240), OpenCvSharp.HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 255));
                        Cv2.PutText(result, "height=" + rect.Size.Height.ToString(), new OpenCvSharp.Point(20, 280), OpenCvSharp.HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 255));
                    }
                }
    
                pictureBox1.Image = result.ToBitmap();
            }
    
    

    六、资料

    「明月清风_@」的博客:
    https://blog.csdn.net/qq_44386034/article/details/125637891
    

    相关文章

      网友评论

        本文标题:C#:轮廓发现与轮廓分析

        本文链接:https://www.haomeiwen.com/subject/zkwmvdtx.html