工业视觉_60:使用机器人美缝\切割\焊接

/* 工业视觉_60:使用机器人美缝\切割\焊接
            未来20年里,最火的行业之一:机器换人,智能使用机器人,传统工业改造成智慧工厂,智慧工业!
            工业视觉,目标很明确:快,准,稳. 快:开发快,运行速度快;准:高精度;稳:稳健可靠
            所以,目前"机器换人"项目大多采用工控电脑,搭建 Windows7+VS2019+EMGU(或AForge+Accord),这一方案见效最快.
            Halcon,Emgu的视觉库都很强大,而AForge+Accord库更全面更丰富(如:数学,人工智能,机器学习).
            直线识别是工业视觉的入门,它常常包括两直线的几何关系(平行,相交,重合),夹角.
            当光线明暗比较均匀时,用统一的阈值可以过滤出直线.
            当光线明暗问题较大时,应该分成小区块处理.
            在使用机器人美缝\切割\焊接时,应该对相机时行纠正畸变,标定,光线均匀恒定等处理, 
            然后,合理的阈值与丰度是提高精度的关键!
             ---------     编撰:    项道德(微信:daode1212),2021-07-10
             */

            //载入照片:
            pictureBox1.Image = Image.FromFile("2D161b_直线与交点.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.Invert().Apply(gray);//翻转成:背景黑色,线段为白色.若已经是背景黑色,线段为白色的图片不用再翻转        
            var ThresholdBinarization = new Accord.Imaging.Filters.Threshold(255-55).Apply(gray);//调节亮度:阈值二值化
            pictureBox1.Image = ThresholdBinarization;
            MSG("阈值二值化后有用信息查看.\r\n 接着,呈现处理结果");

            //转为非托管数据:
            Accord.Imaging.UnmanagedImage image = Accord.Imaging.UnmanagedImage.FromManagedImage(ThresholdBinarization);

            //建立霍夫变换器:
            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.25"上提取直线: 0.1:高敏感, 0.9:低敏感
            HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(0.25);

            //创建新24位位图的非托管数据:
            // var bmpData = Accord.Imaging.UnmanagedImage.Create(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb);
            //复制原24位位图到非托管数据:
            var bmpData = Accord.Imaging.UnmanagedImage.FromManagedImage(bmp);

            string txt = "Radius\tTheta\r\n";//半径(直线到原点的距离),方位角

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

                // 翻转R(直线到原点的距离)是负数的线段:
                if (r < 0)
                {
                    t += 180;
                    r = -r;
                }

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

                //计算图像的中心点:
                int w2 = ww / 2;
                int h2 = hh / 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.FromArgb(255, 255, 0));
            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("", 10), bh, pp.Value.X - 24, pp.Value.Y + 4);
                }                
            }
            
            g.DrawString("机器人美缝,切割,焊接\r\n" + txt, new Font("", 10), bh, bmp2.Width / 3, 30);
            textBox1.Text = txt;

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值