工业视觉_57:霍夫(Hough)直线识别,交点与夹角

            /* 工业视觉_57:霍夫(Hough)直线识别,交点与夹角
             * 工业视觉,目标很明确:快,准,稳. 快:开发快,运行速度快;准:高精度;稳:稳健
             * 所以,目前"机器换人"项目大多采用工控电脑,搭建 Windows7+VS2019+EMGU(或AForge+Accord),这一方案见效最快.
             * Hacon,Emgu的视觉库都很强大,而AForge+Accord库更全面更丰富(如:数学,人工智能,机器学习).
             * 直线识别是工业视觉的入门,它常常包括两直线的几何关系(平行,相交,重合),夹角.
             * 就单一直线而言,中学数学有多种直线方程,如两点式,点斜式,截距式,一般式.
             * 霍夫(Hough)所提出的直线的表述方法是: 1,直线到原点的距离R; 2,直线的方位角Theta(返回四象限的反正切:Atan2(y,x))
             * Hough算法的核心思想是进行大量的投票统计.
             * 在自动化行业,常常与机器人协作,如钻孔,激光切割,那些交点坐标,夹角大小都是必需的.
             * 霍夫(Hough)直线检测的官方例程(C#语言)在:
             http://accord-framework.net/docs/html/T_Accord_Imaging_HoughLine.htm
             ---------     编撰:    项道德(微信:daode1212),2021-07-07
             */

            pictureBox1.Image = Image.FromFile("工业视觉_5(直线拟合).png"); //     2D161_直线与交点mini.jpg,2D106_直线与圆.jpg,      
            Bitmap bmp = (Bitmap)(pictureBox1.Image);
            int ww = bmp.Width;
            int hh = bmp.Height;
            //自定: MSG("")为内置函数MessageBox.Show("")的简写方式;
            MSG("图片宽度与高度:\r\n"+string.Format("w={0},h={1}",ww,hh)+"\r\n 接着,呈现处理结果");                        

          
            var gray = new Accord.Imaging.Filters.Grayscale(0.3, 0.6, 0.1).Apply(bmp); //转为灰度位图
            //gray = new Accord.Imaging.Filters.Threshold(100).Apply(gray);//调节亮度阈值
            gray = new Accord.Imaging.Filters.Invert().Apply(gray);//翻转成:背景黑色,线段为白色.    背景黑色,线段为白色的图片不用再翻转        
            
            //转为非托管数据:
            Accord.Imaging.UnmanagedImage image = Accord.Imaging.UnmanagedImage.FromManagedImage(gray);

            //建立霍夫变换器:
            HoughLineTransformation lineTransform = new HoughLineTransformation();           
           
            //霍夫变换器处理数据:
            lineTransform.ProcessImage(image);
            Bitmap houghLineImage = lineTransform.ToBitmap();

            中间处理数据真像:
            pictureBox1.Image = houghLineImage;
            MSG("中间投票统计处理数据真像,\r\n接着,继续呈现处理结果");


            //为几何处理,创建线段列表:
            List<Accord.Math.Geometry.Line> LL = new List<Accord.Math.Geometry.Line>();


            //在"相对密集度=0.5"上提取直线: 0.15:高敏感, 0.75:低敏感
            HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(0.5);

            //创建非托管24位数据:
            var bmpData =Accord.Imaging.UnmanagedImage.Create(bmp.Width,bmp.Height,PixelFormat.Format24bppRgb);

            string txt = "Radius\tTheta\r\n";

            //绘制各直线:
            foreach (HoughLine line in lines)
            {
                //读取每一直线的半径(直线到原点的距离),方位角(-180...+180)
                int r = line.Radius;
                double t = line.Theta;

                // 翻转方位角是负数的线段:
                if (r < 0)
                {
                    t += 180;
                    r = -r;
                }

                //转换角度制为弧度制:
                t = (t / 180) * Math.PI;

                //计算图像的中心点:
                int w2 = bmp.Width / 2;
                int h2 = bmp.Height / 2;

                double x0 = 0, x1 = 0, y0 = 0, y1 = 0;

                if (line.Theta != 0)
                {
                    //非垂直方向的线:
                    x0 = -w2; // 最左点,most left point
                    x1 = w2;  // 最右点,most right point

                    // 计算Y坐标:
                    y0 = (-Math.Cos(t) * x0 + r) / Math.Sin(t);
                    y1 = (-Math.Cos(t) * x1 + r) / Math.Sin(t);
                }
                else
                {
                    // 若正好是垂直方向的线:
                    x0 = line.Radius;
                    x1 = line.Radius;

                    y0 = h2;
                    y1 = -h2;
                }

                txt += line.Radius+"\t"+ line.Theta + "\r\n";

                //绘制直线到bmpData中:
                Drawing.Line(bmpData,
                    new Accord.IntPoint((int)x0 + w2, h2 - (int)y0),
                    new Accord.IntPoint((int)x1 + w2, h2 - (int)y1),
                    Color.Red);
                
                //每一线段加入到列表中:
                var Li = Accord.Math.Geometry.Line.FromPoints(
                    new Accord.IntPoint((int)x0 + w2, h2 - (int)y0),
                    new Accord.IntPoint((int)x1 + w2, h2 - (int)y1));
                LL.Add(Li);
            }

            //转到托管图像后,添加一些注释:
            Bitmap bmp2= bmpData.ToManagedImage();
            Graphics g = Graphics.FromImage(bmp2);
            Pen pen0 = new Pen(Color.FromArgb(100, 0, 0), 2);
            SolidBrush bh = new SolidBrush(Color.AliceBlue);
            LL.Add(LL.ElementAt(0));//为形成封闭
            for (int i=1;i<LL.Count;i++)
            {
                var l1=LL.ElementAt(i-1);
                var l2=LL.ElementAt(i);
                var pp = l1.GetIntersectionWith(l2);//获取两直线交点,null:无交点,两直线重合时抛出异常"System.InvalidOperationException": Thrown if the specified line is the same line as this line.
                var aa = l1.GetAngleBetweenLines(l2);//输出相交直线的最小角(0...90)
                if (pp != null)
                {
                    g.FillEllipse(bh, pp.Value.X - 4, pp.Value.Y - 4, 8, 8);
                    g.DrawString(string.Format("夹角:{0:#.##}度\r\nP({1:#.##},{2:#.##})",aa, pp.Value.X, pp.Value.Y), new Font("",14), bh, pp.Value.X - 24, pp.Value.Y + 4);
                }
            }
            g.DrawString("霍夫(Hough)直线识别,交点与夹角", new Font("", 14), bh,bmp2.Width/3, bmp2.Height-30);
            textBox1.Text = txt;

            //非托管转变为托管对象,并绘制到控件中:
            pictureBox1.Image = bmp2;

 

工业视觉_5(直线拟合).png

 效果图

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值