EmguCV学习笔记 C# 6.5 凸包和凸缺陷

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。

教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客

教程C#版本请访问:EmguCV学习笔记 C# 目录-CSDN博客

笔者的博客网址:https://blog.csdn.net/uruseibest

教程配套文件及相关说明以及如何获得pdf教程和代码,请移步:EmguCV学习笔记

学习VB.Net知识,请移步: vb.net 教程 目录_vb中如何用datagridview-CSDN博客

 学习C#知识,请移步:C# 教程 目录_c#教程目录-CSDN博客

6.5 凸包和凸缺陷

凸包是一个点集的凸多边形包围,即包含该点集的最小凸多边形。在计算机视觉和图像处理中,凸包常用于轮廓分析和形状检测等任务中。

凸缺陷是指凸多边形内部的空洞或空隙,即凸包与轮廓之间的空隙。在计算凸性缺陷时,我们需要先计算轮廓的凸包,然后计算凸包与轮廓之间的空隙。

6.5.1 凸包检测ConvexHull

CvInvoke.ConvexHull方法用于计算给定轮廓的凸包。凸包是能够包含所有轮廓点的最小凸多边形。该方法声明如下:

public static void ConvexHull(

           IInputArray points,

                    IOutputArray hull,

                    bool clockwise = false,

           bool returnPoints = true

)

参数说明:

  1. points:要计算凸包的轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours。
  2. hull:返回凸包顶点。
  3. clockwise:凸包顶点的顺序。True,表示获得的凸包顶点顺序为顺时针;否则为逆时针。
  4. returnPoints:是否返回凸包顶点的坐标。True,表示返回凸包顶点的坐标,此时hull为VectorOfPoint类型;否则为凸包顶点的索引,此时hull为VectorOfInt类型。

【代码位置:frmChapter6】Button20_Click

        //凸包检测

        private void Button20_Click(object sender, EventArgs e)

        {

            Mat msrc = new Mat("C:\\learnEmgucv\\hand.jpg", ImreadModes.AnyColor);

            ImageBox1.Image = msrc;

            //二值化

            Mat gray = new Mat();

            CvInvoke.CvtColor(msrc, gray, ColorConversion.Bgr2Gray);

            Mat mb = new Mat();

            CvInvoke.Threshold(gray, mb, 240, 255, ThresholdType.BinaryInv);

            //进行一次开运算消除小的噪点

            Mat k = new Mat();

            k = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));

            CvInvoke.MorphologyEx(mb, mb, MorphOp.Open, k, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(0));

            ImageBox2.Image = mb;

            //获得轮廓

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

            VectorOfRect hierarchy = new VectorOfRect();

            CvInvoke.FindContours(mb, contours, hierarchy, RetrType.List, ChainApproxMethod.ChainApproxSimple);

            VectorOfPoint hull = new VectorOfPoint();

            //凸包检测,这里为简化,只有一个形状,其余参数使用默认值

            CvInvoke.ConvexHull(contours[0], hull);

            Mat mdst = new Mat();

            mdst = msrc.Clone();

            //绘制凸包顶点

            for (int i = 0; i < hull.Size; i++)

                CvInvoke.Circle(mdst, hull[i], 3, new MCvScalar(0, 0, 255), -1);

            ImageBox3.Image = mdst;

        }

运行后如下图所示:

 

图6-21 获得凸包顶点

6.5.2 凸缺陷 ConvexityDefects

`CvInvoke.ConvexityDefects`是EmguCV中的一个方法,用于计算凸性缺陷,它需要三个参数:

public static void ConvexityDefects(

           IInputArray contour,

                    IInputArray convexhull,

           IOutputArray convexityDefects

)

  1. contour:要计算凸缺陷的轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours。
  2. convexhull:轮廓的凸包索引,类型为VectorOfInt。凸包可以使用CvInvoke.ConvexHull方法计算得到,其中ConvexHull方法的参数hull 应设置为VectorOfInt;参数returnPoints应设置为False。
  3. convexityDefects:输出的凸缺陷,这是一个包含四个数据的数组,它包含以下数据:1、凸包顶点的起点索引;2、凸包顶点的终点索引;3、轮廓上距离凸包最远的点;4、最远点到凸包的近似距离。在实际开发中,可以使用VectorOfRect来实现此数组。

注意:ConvexityDefects方法计算得到的凸缺陷可能包含一些无用的凸缺陷,这些凸缺陷的长度可能非常小,并且与实际凸缺陷无关。因此,我们需要在画凸缺陷时进行一些处理,只画出长度大于一定阈值的凸缺陷。

【代码位置:frmChapter6】Button21_Click

        //凸缺陷

        private void Button21_Click(object sender, EventArgs e)

        {

            Mat msrc = new Mat("C:\\learnEmgucv\\hand.jpg", ImreadModes.AnyColor);

            ImageBox1.Image = msrc;

            Mat gray = new Mat();

            CvInvoke.CvtColor(msrc, gray, ColorConversion.Bgr2Gray);

            Mat mb = new Mat();

            CvInvoke.Threshold(gray, mb, 240, 255, ThresholdType.BinaryInv);

            Mat k = new Mat();

            k = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));

            CvInvoke.MorphologyEx(mb, mb, MorphOp.Open, k, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(0));

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

            VectorOfRect hierarchy = new VectorOfRect();

            CvInvoke.FindContours(mb, contours, hierarchy, RetrType.List, ChainApproxMethod.ChainApproxSimple);

            VectorOfPoint hullpoint = new VectorOfPoint();

            VectorOfInt hullint = new VectorOfInt();

            //1、为简化,这里只有一个形状

            //2、要使用ConvexityDefects,必须将ConvexHull参数returnPoints设置为false,也就是说需要的是凸包顶点的索引,

            //不使用以下方法

            CvInvoke.ConvexHull(contours[0], hullpoint, false, true);

            //使用以下方法:

            CvInvoke.ConvexHull(contours[0], hullint, false, false);

            VectorOfRect cd = new VectorOfRect();

            //获得凸缺陷

            CvInvoke.ConvexityDefects(contours[0], hullint, cd);

            Mat mdst1 = new Mat();

            mdst1 = msrc.Clone();

            //获得凸缺陷点

            for (int i = 0; i < cd.Size; i++)

            {

                int startIndex = cd[i].X;     //凸包顶点的起点索引

                int endIndex = cd[i].Y;       //凸包顶点的终点索引

                int farIndex = cd[i].Width;   //轮廓上距离凸包最远的点的索引

                int dis = cd[i].Height;       //最远点到凸包的近似距离

                //Console.WriteLine(startIndex + " " + endIndex + " " + farIndex + " " + dis);

                Point startPoint = contours[0][startIndex];   //凸包顶点起点的坐标

                Point endPoint = contours[0][endIndex];       //凸包顶点终点的坐标

                Point farPoint = contours[0][farIndex];       //凸缺陷点的坐标

                //连接凸包顶点

                CvInvoke.Line(mdst1, startPoint, endPoint, new MCvScalar(128, 128, 0), 2);

                //绘制凸缺陷点

                CvInvoke.Circle(mdst1, farPoint, 5, new MCvScalar(0, 0, 255), -1);

            }

            ImageBox2.Image = mdst1;

            Mat mdst2 = new Mat();

            mdst2 = msrc.Clone();

            //获得凸缺陷点

            for (int i = 0; i < cd.Size; i++)

            {

                int startIndex = cd[i].X;

                int endIndex = cd[i].Y;

                int farIndex = cd[i].Width;

                int dis = cd[i].Height;

                Point startPoint = contours[0][startIndex];

                Point endPoint = contours[0][endIndex];

                Point farPoint = contours[0][farIndex];

                //连接凸包顶点

                CvInvoke.Line(mdst2, startPoint, endPoint, new MCvScalar(128, 128, 0), 2);

                //排除无用的凸缺陷

                if (dis > 5000)

                    //绘制凸缺陷点

                    CvInvoke.Circle(mdst2, farPoint, 5, new MCvScalar(0, 0, 255), -1);

            }

            ImageBox3.Image = mdst2;

        }

运行后如下图所示,其中第三幅图是使用距离作为判断依据,排除了无用的凸缺陷点:

 

图6-22 获得凸缺陷点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值