工业视觉_58:常见图形(三角形,四边形,圆,多边形)的判别

/*             
            工业视觉_58:常见图形(三角形,四边形,圆,多边形)的判别
           * 机器人工业应用中常常要执行分拣铁片,布片,塑料片等任务.
           * 确定基本图形(三角形,四边形,圆,多边形)的类别,是机器视觉能力的简单表现.
           * 在产品的分拣中,摄像头传入的是照片,要用"连通域-->关键点",或"轮廓-->角点"等提取本文中的点集,再进行图形识别分类.
           * 其他异形的图形,如苹果形,心形,花瓣形,手掌形,瓢形.它们的识别与定位,方位角的识别等,见我自己的算法,在另一篇论述.
           
           * 工业视觉,目标很明确:快,准,稳. 快:开发快,运行速度快;准:高精度;稳:稳健
           * 在嵌入式中编写,找到合适的库函数最好,如果没有,自己要重新编写很多库函数. 
           * 所以,目前"机器换人"项目大多采用工控电脑,搭建 Windows7+VS2019+EMGU(或AForge+Accord,或Halcon),这一方案见效最快.
           * Halcon,Emgu的视觉库都很强大,而AForge+Accord库更全面更丰富(如:数学,人工智能,机器学习).
           * 
           * 在自动化行业的机器视觉,常常与机器人或车床协作,如分拣,钻孔,激光切割,计算各类数据都是必需的.
           * Accord.SimpleShapeChecker中IsConvexPolygon使用时要谨慎,它仍不够成熟.
                                  ---------     编撰:    项道德(微信:daode1212),2021-07-09
           */

            //pictureBox1.Image = Image.FromFile("2D106_直线与圆.jpg");
            //Bitmap bmp = (Bitmap)(pictureBox1.Image);

            Bitmap bmp = new Bitmap(800,800);
            int ww = bmp.Width;
            int hh = bmp.Height;
            Graphics g = Graphics.FromImage(bmp);
            SolidBrush bh = new SolidBrush(Color.FromArgb(0, 120, 0));
            Pen pen0 = new Pen(Color.FromArgb(255, 0, 0), 4);
            Pen pen1 = new Pen(Color.FromArgb(220, 220, 0), 3);
            Pen pen2 = new Pen(Color.FromArgb(0, 0, 220), 2);
            Pen pen3 = new Pen(Color.FromArgb(150, 0, 150), 1);
            int x0 = ww / 2;
            int y0 = hh / 2;


            MSG("图片宽度与高度:" + string.Format("w={0},h={1}", ww, hh) + "\r\n 接着,呈现处理结果");

            List<IntPoint> idealCicle = new List<IntPoint>();//理想的圆
            List<IntPoint> distorredCircle = new List<IntPoint>();//扭曲的圆
            System.Random rand = new System.Random();

            // 生成一些圆,generate sample circles 
            float radius = 120;
            for (int i = 0; i < 360; i += 10)
            {
                float angle = (float)((float)i / 180 * System.Math.PI);
                // 添加一个理想的圆,add point to ideal circle
                idealCicle.Add(new IntPoint(x0-200+(int)(radius * System.Math.Cos(angle)),y0+ (int)(radius * System.Math.Sin(angle))));
                // 添加位失真圆,  add a bit distortion for distorred circle 
                float distorredRadius = radius + rand.Next(12) - 6;
                distorredCircle.Add(new IntPoint(x0+200+(int)(distorredRadius * System.Math.Cos(angle)), y0+(int)(distorredRadius * System.Math.Sin(angle))));

                g.FillEllipse(bh, x0-200+(int)(radius * System.Math.Cos(angle))-4, y0+(int)(radius * System.Math.Sin(angle))-4,8,8);
                g.FillEllipse(bh, x0+200+(int)(distorredRadius * System.Math.Cos(angle))-4, y0+(int)(distorredRadius * System.Math.Sin(angle))-4,8,8);
            }

            Point[] pt1 = PointsListToArray(idealCicle);
            g.DrawPolygon(pen0, pt1);

            Point[] pt2 = PointsListToArray(distorredCircle);
            g.DrawPolygon(pen1, pt2);


            // 检查形状,check shape:
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
            /* 以下诸神器也常常要用的:
             * shapeChecker.CheckShapeType : 
             * shapeChecker.IsCircle,  
             * shapeChecker.IsConvexPolygon, 
             * shapeChecker.IsQuadrilateral,   
             * shapeChecker.IsTriangle,*/

            if (shapeChecker.IsCircle(idealCicle))//标准的圆
            {
                g.DrawString("idealCicle:IsCircle", new Font("", 12), bh, idealCicle.ElementAt(9).X-100, idealCicle.ElementAt(9).Y);
            }
            if (shapeChecker.CheckShapeType(distorredCircle) == ShapeType.Circle)//非标准的圆
            {
                g.DrawString("distorredCircle:IsCircle", new Font("", 12), bh, distorredCircle.ElementAt(9).X-100, distorredCircle.ElementAt(9).Y);
            }

            //对于凹多边形的非标准的圆,获取其凸壳:
            IConvexHullAlgorithm hullFinder1 = new GrahamConvexHull(); List<IntPoint> hull1 = hullFinder1.FindHull(distorredCircle);
            g.DrawPolygon(pen3, PointsListToArray(hull1));

            //=============  另一些几何图形:  ==============

            //判断一个三角形:
            IntPoint[] pt3 = {
              new IntPoint(176,68), new IntPoint(312,202), new IntPoint(64,257)
            };
            List<IntPoint> Triangle =pt3.ToList();
            g.DrawPolygon(pen2, PointsListToArray(Triangle));
            if (shapeChecker.IsTriangle(Triangle))
            {
                g.DrawString("IsTriangle", new Font("", 12), bh, Triangle.ElementAt(0).X - 100, Triangle.ElementAt(0).Y);
            }

            //判断一个四边形:
            IntPoint[] pt4 = {
              new IntPoint(462,82), new IntPoint(614,66), new IntPoint(717,250), new IntPoint(447,230)
            };
            List<IntPoint> Quad = pt4.ToList();
            g.DrawPolygon(pen2, PointsListToArray(Quad));
            if (shapeChecker.IsQuadrilateral(Quad))
            {
                g.DrawString("IsQuad", new Font("", 12), bh, Quad.ElementAt(0).X - 100, Quad.ElementAt(0).Y);
            }

            //判断一个凹多边形:
            IntPoint[] pt7 = {
                new IntPoint(574,681), 
                new IntPoint(647,688), 
                new IntPoint(728,727), 
                new IntPoint(757,700), 
                new IntPoint(658,568), 
                new IntPoint(584,637), 
                new IntPoint(485,689)
            };
            List<IntPoint> PolygonA = pt7.ToList();
            List<IntPoint> cornersA = new List<IntPoint>();//面积最大的四边形:四个角的坐标(x,y)
            g.DrawPolygon(pen0, PointsListToArray(PolygonA));
            if (shapeChecker.IsConvexPolygon(PolygonA,out cornersA))
            {
                g.DrawString("IsConvexPolygon", new Font("", 12), bh, PolygonA.ElementAt(0).X - 100, PolygonA.ElementAt(0).Y);
            }
            if (!shapeChecker.IsConvexPolygon(PolygonA, out cornersA))
            {
                g.DrawString("Convex Polygon ?", new Font("", 12), bh, PolygonA.ElementAt(4).X - 100, PolygonA.ElementAt(4).Y);
            }
            g.DrawPolygon(pen2, PointsListToArray(cornersA));

            //对于凹多边形的,获取其凸壳:
            IConvexHullAlgorithm hullFinder2 = new GrahamConvexHull(); List<IntPoint> hull2 = hullFinder2.FindHull(PolygonA);
            g.DrawPolygon(pen3, PointsListToArray(hull2));

            //再判断一个凸边形:
            IntPoint[] pt7b = {
                new IntPoint(74,581),
                new IntPoint(164,566),
                new IntPoint(428,597),
                new IntPoint(357,700),
                new IntPoint(158,748),
                new IntPoint(54,737),
                new IntPoint(35,639)
            };
            List<IntPoint> PolygonB = pt7b.ToList();
            List<IntPoint> cornersB = new List<IntPoint>();//面积最大的四边形:四个角的坐标(x,y)
            g.DrawPolygon(pen0, PointsListToArray(PolygonB));
            if (shapeChecker.IsConvexPolygon(PolygonB, out cornersB))
            {
                g.DrawString("IsConvexPolygon", new Font("", 12), bh, PolygonB.ElementAt(4).X - 100, PolygonB.ElementAt(4).Y);
            }
            if (!shapeChecker.IsConvexPolygon(PolygonB, out cornersB))
            {
                g.DrawString("Convex Polygon ?", new Font("", 12), bh, PolygonB.ElementAt(4).X - 100, PolygonB.ElementAt(4).Y);
            }
            g.DrawPolygon(pen2, PointsListToArray(cornersB));

            //更新控件显示:
            pictureBox1.Image = bmp;

            /*
                 The class performs checking/detection of some simple geometrical shapes for provided set of points (shape's edge points). During the check the class goes through the list of all provided points and checks how accurately they fit into assumed shape.
            All the shape checks allow some deviation of points from the shape with assumed parameters. In other words it is allowed that specified set of points may form a little bit distorted shape, which may be still recognized. The allowed amount of distortion is controlled by two properties (Accord.Math.Geometry.SimpleShapeChecker.MinAcceptableDistortion and Accord.Math.Geometry.SimpleShapeChecker.RelativeDistortionLimit), which allow higher distortion level for bigger shapes and smaller amount of distortion for smaller shapes. Checking specified set of points, the class calculates mean distance between specified set of points and edge of the assumed shape. If the mean distance is equal to or less than maximum allowed distance, then a shape is recognized. The maximum allowed distance is calculated as:
            maxDistance = max( minAcceptableDistortion, relativeDistortionLimit * ( width + height ) / 2 )
            , where width and height is the size of bounding rectangle for the specified points.
            See also Accord.Math.Geometry.SimpleShapeChecker.AngleError and Accord.Math.Geometry.SimpleShapeChecker.LengthError properties, which set acceptable errors for polygon sub type checking done by Accord.Math.Geometry.SimpleShapeChecker.CheckPolygonSubType(System.Collections.Generic.List{Accord.IntPoint}) method.
            See the next article for details about the implemented algorithms: Detecting some simple shapes in images.
                 以下的百度机器翻译,可作参考:
                 该类为提供的一组点(形状的边缘点)执行一些简单几何形状的检查/检测。在检查的过程中,这个类将检查所有提供的点的列表,并检查它们是否精确地符合假定的形状。
            所有形状检查都允许点与具有假定参数的形状有一些偏差。换言之,允许指定的一组点形成一点扭曲的形状,这仍然可以被识别。允许的失真量由两个属性(Accord.Math.Geometry.SimpleShapeChecker.minAcceptable畸变和Accord.Math.Geometry.SimpleShapeChecker.relativeStorionLimit)控制,这两个属性允许较大形状的失真度更高,较小形状的失真度更小。通过检查指定的点集,类计算指定点集和假定形状的边之间的平均距离。如果平均距离等于或小于最大允许距离,则识别形状。最大允许距离计算如下:
            最大距离=最大值(最小可接受失真,相对失真极限*(宽度+高度)/2)
            ,其中宽度和高度是指定点的边框大小。
            另请参见Accord.Math.Geometry.SimpleShapeChecker.AngleError和Accord.Math.Geometry.SimpleShapeChecker.LengthError属性,它们为Accord.Math.Geometry.SimpleShapeChecker.CheckPolygonSubType(System.Collections.Generic.List{Accord.IntPoint})方法执行的多边形子类型检查设置可接受的错误。
            有关实现的算法的详细信息,请参阅下一篇文章:检测图像中的一些简单形状。
             */

工业视觉_58:常见图形(三角形,四边形,圆,多边形)的判别

上一篇:流媒体传输协议之 RTP (上篇)


下一篇:昨晚凌晨1点58分,产品1.0版本上线了