c# + Emgu.CV学习(三):边缘检测、霍夫圆、霍夫线检测、矩形三角形检测


一、边缘检测

提取边缘:根据灰度的差值来获取边缘

1、Canny算子

            // 提取边缘
            // 使用canny算子,阈值1和阈值2中的最小值用于边缘。
            // 参数:输入图片,输出图片,阈值1,阈值2
            //大于高阈值,强边缘点;小于高阈值高于低阈值,弱边缘点;小于低阈值,过滤。
            //滞后边界跟踪:强边缘点被认为是真边缘点,弱边缘可能是真边缘也可能是噪声引起的假边缘点。只有当假边缘点连接到真边缘点时,保留假边缘点,否则去除。
            CvInvoke.Canny(grayImage, cannyImg, 20, 40);

2、Soble算子

            //提取边缘
            //Sobel算子,参数:输入图片,输出图片,图像深度,x 方向上的几阶导数,y 方向上的几阶导数
            CvInvoke.Sobel(grayImage, sobelImage, grayImage.Depth, 1, 0);

3、Laplacian算子

            //提取边缘
            //Laplacian算子 参数:输入图片,输出图片,图像深度,二阶导数滤波器的孔径大小,拉普拉斯值的可选比例因子,结果存储到之前添加到结果中的可选增量值
            CvInvoke.Laplacian(grayImage, LaplacianImage, grayImage.Depth, 3, 1, 0);

4、三种算子的优缺点

        //1、Canny 不容易受噪声干扰,使用两种不同的阈值能够检测到真正的弱边缘      容易把噪点误判为边界     常用
        //2、Sobel 对灰度渐变和噪声较多的图像处理效果较好                        精度不高                精度要求不高时常用
        //3、Laplacian 无方向性,对任何走向的界线和线条进行锐化                  对噪声特别敏感          一般图像用的较少

二、霍夫检测

1、霍夫圆检测

 private void 霍夫圆检测ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Mat readImage = new Mat();
            //为了简便、封装的获取图片方法
            ClassStatic.readImage("7", ClassStatic.Jpg, ref readImage);
            Mat grayImage = new Mat();
            //转化为灰度
            CvInvoke.CvtColor(readImage, grayImage, ColorConversion.Rgb2Gray);
            Mat blurImage = new Mat();
            //高斯滤波
            CvInvoke.GaussianBlur(grayImage, blurImage, new Size(5, 5), 3);

            //霍夫圆检测  
            //参数:输入图像,实现方法,dp,最小距离,参数1,参数2,最小圆半径,最大圆半径
            //dp:累加器分辨率与图像分辨率的反比。例如,如果dp=1,累加器的分辨率与输入图像相同。如果dp=2,则蓄能器的宽度和高度为原来的一半。
            //最小距离:检测到的圆的中心之间的最小距离。太小会多检,太大会漏检
            //参数1:在CV_HOUGH_GRADIENT梯度的情况下,它是传递给Canny()边缘检测器的两个阈值中的较高阈值(较低的阈值是较小的两倍)。
            //参数2:在CV_HOUGH_GRADIENT梯度的情况下,它是检测阶段圆心的累加器阈值。越小,可得到越多的圆。与较大累加器值相对应的圆将首先返回。
            CircleF[] circles = CvInvoke.HoughCircles(blurImage, HoughModes.Gradient, 2, 20, 100, 180, 5);
            Image<Bgr, byte> image = readImage.ToImage<Bgr, byte>().Copy();
            foreach (CircleF circle in circles)
            {
                //画一个特定颜色和厚度的圆 参数:要绘制的圆,圆的颜色,厚度:如果厚度小于1,则填充圆
                image.Draw(circle, new Bgr(Color.Blue), 4);
            }
            CvInvoke.Imshow("circle image", image);
        }

2、霍夫线检测

private void 霍夫线检测ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Mat readImage = new Mat();
            //为了简便、封装的获取图片方法
            ClassStatic.readImage("8", ClassStatic.Jpg, ref readImage);
            Mat grayImage = new Mat();
            //转化为灰度
            CvInvoke.CvtColor(readImage, grayImage, ColorConversion.Rgb2Gray);
            Mat blurImage = new Mat();
            //高斯滤波
            CvInvoke.GaussianBlur(grayImage, blurImage, new Size(5, 5), 3);
            Mat cannyImage = new Mat();
            //canny算子提取边缘
            CvInvoke.Canny(blurImage, cannyImage, 100, 120);

            //霍夫线检测
            //参数: 输入图形、累加器的距离分辨率(像素)、累加器的角度分辨率(弧度)、阈值、最小长度、最大间隙
            LineSegment2D[] lines = CvInvoke.HoughLinesP(cannyImage, 1, Math.PI / 20, 30, 80, 30);
            Image<Bgr, Byte> image = readImage.ToImage<Bgr, Byte>().Copy();
            foreach (LineSegment2D line in lines)
            {
                //绘制线 参数:要绘制的线,线的颜色,线条粗细
                image.Draw(line, new Bgr(Color.HotPink), 2);
            }

            CvInvoke.Imshow("Line Image", image);
        }

3、矩形三角形检测

        private void 矩形三角形检测ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Mat readImage = new Mat();
            ClassStatic.readImage("9", ClassStatic.Jpg, ref readImage);
            Mat grayImage = new Mat();
            CvInvoke.CvtColor(readImage, grayImage, ColorConversion.Rgb2Gray);
            Mat blurImage = new Mat();
            CvInvoke.GaussianBlur(grayImage, blurImage, new Size(3, 3), 3);
            Mat cannyImage = new Mat();
            CvInvoke.Canny(blurImage, cannyImage, 60, 180);
            CvInvoke.Imshow("", cannyImage);

            List<Triangle2DF> triangleList = new List<Triangle2DF>();  //三角形列表
            List<RotatedRect> rectList = new List<RotatedRect>();//矩形列表
            //using(){}当我们做一些比较占用资源的操作,在此范围的末尾自动将对象释放。
            //VectorOfVectorOfPoint:创建一个空的VectorOfPoint标准向量
            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                //  参数:输入图像,点向量,,检索类型,方法
                CvInvoke.FindContours(cannyImage, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                for (int i = 0; i < contours.Size; i++)
                {
                    using (VectorOfPoint contour = contours[i])  //点的标准矢量
                    using (VectorOfPoint approxContour = new VectorOfPoint())
                    {
                        // CvInvoke.ApproxPolyDP:指定精度的多边形曲线  参数:输入向量(轮廓),近似轮廓,近似精度,true:则闭合形状
                        // CvInvoke.ArcLength:计算轮廓长度   参数:轮廓,曲线是否闭合
                        CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.08, true);  //0.08的相似度
                        //CvInvoke.ContourArea:计算轮廓面积  参数:轮廓,返回值是否为绝对值
                        //仅考虑面积大于50的轮廓
                        if (CvInvoke.ContourArea(approxContour, false) > 50)
                        {
                            if (approxContour.Size == 3)//轮廓有3个顶点:三角形
                            {
                                Point[] points = approxContour.ToArray(); //转化为数组
                                triangleList.Add(new Triangle2DF(points[0], points[1], points[2]));
                            }
                            else if (approxContour.Size == 4)//轮廓有4个顶点:矩形
                            {
                                bool isRect = true;
                                Point[] points = approxContour.ToArray();
                                LineSegment2D[] rects = PointCollection.PolyLine(points, true);
                                for (int j = 0; j < rects.Length; j++)
                                {
                                    double angle = Math.Abs(
                                        rects[(j + 1) % rects.Length].GetExteriorAngleDegree(rects[j]));
                                    //角度在小于80,大于100,判定不是矩形
                                    if (angle < 80 || angle > 100)
                                    {
                                        isRect = false;
                                        break;
                                    }
                                }
                                if (isRect) { rectList.Add(CvInvoke.MinAreaRect(approxContour)); }
                            }
                        }
                    }
                }

            }

            //展示结果
            //三角形
            Image<Bgr, Byte> image = readImage.ToImage<Bgr, Byte>().Copy();
            foreach (Triangle2DF triangle in triangleList)
            {
                image.Draw(triangle, new Bgr(Color.Red), 2);
            }
            CvInvoke.Imshow("Triangle Image", image);
            //矩形
            Image<Bgr, Byte> iamge1 = readImage.ToImage<Bgr, Byte>().Copy();
            foreach (RotatedRect rect in rectList)
            {
                iamge1.Draw(rect, new Bgr(Color.Red), 2);
            }
            CvInvoke.Imshow("Rect Image", iamge1);
            CvInvoke.WaitKey();
        }
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值