EmguCV学习笔记 VB.Net 6.3 轮廓外接多边形

news2024/10/1 21:36:27

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

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.3 轮廓外接多边形

6.3.1 最大外接矩形BoundingRectangle 

CvInvoke.BoundingRectangle方法用于获得轮廓的最大外接矩形。该方法其中一个声明:

Public Shared Function BoundingRectangle(points As Emgu.CV.IInputArray) As System.Drawing.Rectangle

参数说明:

  1. points:要计算最大外接矩形的轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours所包含的成员。

返回值:

返回一个Rectangle对象,表示计算得到的最大矩形的位置和大小。

代码参看6.3.2节【minAreaRect】中的示例。

6.3.2 最小外接矩形minAreaRect

在Emgu.CV中,CvInvoke.MinAreaRect函数用于计算轮廓的最小外接矩形。它的用法如下:

Public Shared Function MinAreaRect(points As Emgu.CV.IInputArray) As Emgu.CV.Structure.RotatedRect

参数说明:

  1. points:要计算最大外接矩形的轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours所包含的成员。

返回值:

返回一个RotatedRect对象,表示计算得到的最小外接矩形。通过RotatedRect的GetVertices方法返回四个顶点,然后可使用CvInvoke.Polylines绘制。

【代码位置:frmChapter6】Button8_Click

    '外接多边形:最大外接矩形 最小外接矩形

    Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click

        Dim msrc As New Mat("C:\learnEmgucv\shape2.jpg", CvEnum.ImreadModes.Color)

        '转灰度

        Dim mgray As New Mat

        CvInvoke.CvtColor(msrc, mgray, ColorConversion.Bgr2Gray)

        '二值化

        Dim mid As New Mat

        CvInvoke.Threshold(mgray, mid, 150, 255, ThresholdType.BinaryInv)

        Dim contours As New VectorOfVectorOfPoint

        Dim hierarchy As New VectorOfRect

        '获得轮廓

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

        '绘制最大外接矩形的图像

        Dim mmax As New Mat

        mmax = msrc.Clone()

        '绘制最小外接矩形的图像

        Dim mmin As New Mat

        mmin = msrc.Clone()

        For i As Integer = 0 To contours.Size - 1

            '获得最大外接矩形

            Dim rectmax As Rectangle = CvInvoke.BoundingRectangle(contours(i))

            CvInvoke.Rectangle(mmax, rectmax, New MCvScalar(255), 2)

            '获得最小外接矩形

            Dim rectmin As RotatedRect = CvInvoke.MinAreaRect(contours(i))

            Dim pf() As PointF = rectmin.GetVertices()

            '实现数组PointF到数组Point的转换

            Dim pf1() As Point = Array.ConvertAll(pf, New Converter(Of PointF, Point)AddressOf PointFToPoint))

            '不能按照矩形绘制,只能绘制多边形

            CvInvoke.Polylines(mmin, pf1, True, New MCvScalar(255, 0, 0), 2)

        Next

        ImageBox2.Image = mmax

        ImageBox3.Image = mmin

End Sub

运行后如下图所示:

图6-9 绘制轮廓的最大外接矩形和最小外接矩形

【代码位置:frmChapter6】Button9_Click

    '外接多边形:最大外接矩形 最小外接矩形

    'Image来代替mat完成最后的绘制

    Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click

        Dim m1 As New Mat("C:\learnEmgucv\shape2.jpg", CvEnum.ImreadModes.Grayscale)

        ImageBox1.Image = m1

        Dim mid1 As New Mat

        CvInvoke.Threshold(m1, mid1, 150, 255, ThresholdType.BinaryInv)

        Dim contours As New VectorOfVectorOfPoint

        Dim hierarchy As New VectorOfRect

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

        Dim m2 As New Image(Of Bgr, Byte)("C:\learnEmgucv\shape2.jpg")

        '最大外接矩形

        Dim mmax As New Image(Of Bgr, Byte)(m2.Width, m2.Height)

        mmax = m2.Clone()

        '最小外接矩形

        Dim mmin As New Image(Of Bgr, Byte)(m2.Width, m2.Height)

        mmin = m2.Clone()

        For i As Integer = 0 To contours.Size - 1

            '最大外接矩形

            Dim rectmax As Rectangle = CvInvoke.BoundingRectangle(contours(i))

            mmax.Draw(rectmax, New Bgr(0, 255, 0), 2)

            '或者以下代码:

            'CvInvoke.Rectangle(mmax, rectmax, New MCvScalar(255), 2)

            Dim rectmin As RotatedRect = CvInvoke.MinAreaRect(contours(i))

            mmin.Draw(rectmin, New Bgr(0, 255, 0), 2)

            '或者以下代码:

            'Dim pf() As PointF = rectmin.GetVertices()

            'Dim pf1() As Point = Array.ConvertAll(pf, New Converter(Of PointF, Point)AddressOf PointFToPoint))

            'CvInvoke.Polylines(mmin, pf1, True, New MCvScalar(255, 0, 0), 2)

        Next

        ImageBox2.Image = mmax

        ImageBox3.Image = mmin

End Sub

运行后如下图所示:

图6-10 绘制轮廓的最大外接矩形和最小外接矩形

6.3.3 多边形逼近ApproxPolyDP       

CvInvoke.ApproxPolyDP方法用于对轮廓进行多边形逼近。声明如下:

Public Shared Sub ApproxPolyDP(curve As Emgu.CV.IInputArray, approxCurve As Emgu.CV.IOutputArray, epsilon As Double, closed As Boolean)

参数说明:

  1. curve:要进行逼近的轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours所包含的成员。
  2. approxCurve:输出逼近后的多边形曲线。
  3. epsilon:逼近精度,即逼近后的多边形曲线与原轮廓的最大距离。
  4. closed:表示逼近后的多边形曲线是否是闭合的。如果为True,表示闭合;如果为False,表示开放。

【代码位置:frmChapter6】Button10_Click

   '外接多边形

    Private Sub Button10_Click(sender As Object, e As EventArgs) Handles Button10.Click

        Dim msrc As New Mat("C:\learnEmgucv\shape2.jpg", CvEnum.ImreadModes.Grayscale)

        ImageBox1.Image = msrc

        Dim mid1 As New Mat

        CvInvoke.Threshold(msrc, mid1, 150, 255, ThresholdType.BinaryInv)

        ImageBox2.Image = mid1

        '查找轮廓

        Dim contours As New VectorOfVectorOfPoint

        Dim hierarchy As New VectorOfRect

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

        Dim mpoly As New Mat(msrc.Size, DepthType.Cv8U, 3)

        mpoly.SetTo(New MCvScalar(255, 255, 255))

        For i As Integer = 0 To contours.Size - 1

            Dim result As New VectorOfPoint

            '获得逼近后的多边形曲线

            CvInvoke.ApproxPolyDP(contours(i), result, 4, True)

            Dim p() As Point

            p = result.ToArray

            '绘制多边形

            CvInvoke.Polylines(mpoly, p, True, New MCvScalar(255, 0, 0), 2)

            '输出多边形的边数

            CvInvoke.PutText(mpoly, p.Length, New Point(p(p.Length - 1).X - 20, p(p.Length - 1).Y), FontFace.HersheyComplex, 1, New MCvScalar(0, 0, 255), 1)

        Next

        ImageBox3.Image = mpoly

End Sub

运行后如下图所示:

图6-11 绘制轮廓外接多边形

6.3.4 最小外接圆MinEnclosingCircle

CvInvoke.MinEnclosingCircle方法用于计算轮廓的最小外接圆。它的声明之一:

Public Shared Function MinEnclosingCircle(points As Emgu.CV.IInputArray) As Emgu.CV.Structure.CircleF

示例参看6.3.6节 【FitEllipse】代码。

6.3.5 最小外接三角形MinEnclosingTriangle

CvInvoke.MinEnclosingTriangle方法用于计算轮廓的最小外接三角形。它的声明如下:

Public Shared Function MinEnclosingTriangle(points As Emgu.CV.IInputArray, triangles As Emgu.CV.IOutputArray) As Double

示例参看6.3.6节 【FitEllipse】代码。

6.3.6 拟合椭圆FitEllipse     

CvInvoke.FitEllipse方法用于拟合给定点集的椭圆。它的声明如下:

Public Shared Function FitEllipse(points As Emgu.CV.IInputArray) As Emgu.CV.Structure.RotatedRect

【代码位置:frmChapter6】Button11_Click

    '最小外接三角形、最小外接圆、拟合椭圆

    Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click

        Dim m1 As New Mat("C:\learnEmgucv\shape2.jpg", CvEnum.ImreadModes.Grayscale)

        'ImageBox1.Image = m1

        Dim mid1 As New Mat

        CvInvoke.Threshold(m1, mid1, 150, 255, ThresholdType.BinaryInv)

        Dim contours As New VectorOfVectorOfPoint

        Dim hierarchy As New VectorOfRect

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

        Dim m2 As New Mat("C:\learnEmgucv\shape2.jpg", CvEnum.ImreadModes.AnyColor)

        '外接三角形

        Dim mtriangle As New Mat

        mtriangle = m1.Clone()

        '外接圆形

        Dim mcircle As New Mat

        mcircle = m1.Clone()

        '拟合椭圆

        Dim mEllipse As New Mat

        mEllipse = m1.Clone()

        Dim triangle As New VectorOfPoint

        For i As Integer = 0 To contours.Size - 1

            Dim trianglearea As Double

            '获得外接三角形

            trianglearea = CvInvoke.MinEnclosingTriangle(contours(i), triangle)

            '使用封闭多边形来绘制三角形,也可以用line来绘制

            CvInvoke.Polylines(mtriangle, triangle, True, New MCvScalar(0), 2)

            Dim cf As CircleF

            cf = CvInvoke.MinEnclosingCircle(contours(i))

            '获得外接圆形

            CvInvoke.Circle(mcircle, New Point(CInt(cf.Center.X), CInt(cf.Center.Y)), cf.Radius, New MCvScalar(0), 2)

            '获得拟合椭圆

            Dim rr As RotatedRect

            rr = CvInvoke.FitEllipse(contours(i))

            CvInvoke.Ellipse(mEllipse, rr, New MCvScalar(0), 2)

        Next

        ImageBox1.Image = mtriangle

        ImageBox2.Image = mcircle

        ImageBox3.Image = mEllipse

End Sub

运行后如下图所示:

图6-12 轮廓的最小外接三角形、最小外接圆、拟合椭圆

6.3.7 拟合直线FitLine

拟合直线是指利用图像中的点集,找到一条最匹配点集的直线,使得该直线能够尽可能地覆盖所有的点。通过拟合直线,可以得到图像中点的分布情况,从而可以进行轮廓提取、边缘检测等操作。例如,在目标检测中,可以通过拟合直线来定位目标对象的位置和方向;在图像处理中,可以通过拟合直线来进行图像的分割、去除噪声、边缘检测等。

在Emgu.CV中,CvInvoke.FitLine函数用于拟合给定点集的直线,它的声明如下:

Public Shared Sub FitLine(points As Emgu.CV.IInputArray, line As Emgu.CV.IOutputArray, distType As Emgu.CV.CvEnum.DistType, param As Double, reps As Double, aeps As Double)

参数说明:

  1. input:输入的点集。
  2. line:输出的直线,这是一个VectorOfFloat类型,包含四个元素,其中line(0),line(1)是一个方向向量;line(2),line(3)是直线上一个点。可以通过此输出获得直线的斜率和截距:

斜率 = line (1) / line (0)

截距 = line (3) – 斜率 * line (2)

  1. distType:距离类型,可以是DistType.L1或者DistType.L2。
  2. param:距离类型的参数,和所选的距离类型有关,值可以设置为0,FitLine本身会自动选择最优化的值。
  3. reps:拟合直线的径向精度,默认为0.01。
  4. aeps:拟合直线的角度精度,默认为0.01。

【代码位置:frmChapter6】Button12_Click

    'FitLine

    Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click

        Dim m As New Mat(500, 500, DepthType.Cv8U, 3)

        Dim rand As New Random()

        Dim pts(19) As Point

        '设置随机点

        For i As Integer = 0 To 19

            Dim x As Integer = rand.Next(0, 500)

            Dim y As Integer = rand.Next(0, 500)

            pts(i) = New Point(x, y)

            CvInvoke.Circle(m, pts(i), 3, New MCvScalar(0, 0, 255), -1)

        Next

        Dim vop As New VectorOfPoint(pts)

        Dim vof As New VectorOfFloat()

        CvInvoke.FitLine(vop, vof, DistType.L2, 0, 0.01, 0.01)

        '计算斜率

        Dim k As Double = vof(1) / vof(0)

        '计算截距

        Dim b As Double = vof(3) - k * vof(2)

        '获得直线起点

        Dim startpoint As New Point(0, CInt(b))

        '获得直线终点

        Dim endpoint As New Point(m.Width - 1, CInt(k * (m.Width - 1) + b))

        CvInvoke.Line(m, startpoint, endpoint, New MCvScalar(255, 0, 0), 2)

        ImageBox1.Image = m

End Sub

运行后如下图所示:

图6-13 获得拟合直线

6.3.8 最短距离pointPolygonTest      

CvInvoke.PointPolygonTest方法用于计算给定点到多边形的最短距离,或判断点是否在多边形内部。该方法声明如下:

Public Shared Function PointPolygonTest(contour As Emgu.CV.IInputArray, pt As System.Drawing.PointF, measureDist As Boolean)

参数说明:

  1. contour:轮廓。这是一个VectorOfPoint类型。对应使用FindContours方法获得的contours所包含的成员。
  2. pt:要计算的点的坐标。
  3. measureDist:如果设置为true,则计算最短距离;如果设置为false,则仅判断点是否在多边形内部。

返回值:

如果measureDist设置为true,则返回给定点到多边形的最短距离,正值表示点在多边形外部,负值表示点在多边形内部。

如果measureDist设置为false,则返回一个整数值:1表示点在多边形内部,0表示点在多边形边界上,-1表示点在多边形外部。

【代码位置:frmChapter6】Button13_Click

    'PointPolygonTest 轮廓外一点到轮廓的距离

    Private Sub Button13_Click(sender As Object, e As EventArgs) Handles Button13.Click

        Dim m As New Mat(400, 400, DepthType.Cv8U, 1)

        m.SetTo(New MCvScalar(0))

        '绘制一个矩形轮廓和一个圆形轮廓

        CvInvoke.Rectangle(m, New Rectangle(50, 50, 100, 100), New MCvScalar(255), -1)

        CvInvoke.Circle(m, New Point(300, 300), 100, New MCvScalar(255), -1)

        Dim m1 As New Mat

        m1 = m.Clone

        Dim p1 As New Point(240, 100)

        Dim contours As New VectorOfVectorOfPoint

        Dim hierarchy As New VectorOfRect

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

        Dim dis As New List(Of Double)

        For i As Integer = 0 To contours.Size - 1

            Dim dis1 As Double = CvInvoke.PointPolygonTest(contours(i), p1, True)

            dis.Add(dis1)

            '只看在轮廓的内外

            '点在轮廓上,返回0,不计算距离返回0

            '点在轮廓内,返回正数,不计算距离返回1

            '点在轮廓外,返回负数,不计算距离返回-1

            'Dim dis2 As Double = CvInvoke.PointPolygonTest(contours(i), p1, False)

            'Console.WriteLine(dis2)

        Next

        CvInvoke.Circle(m1, p1, 2, New MCvScalar(255), -1)

        ImageBox1.Image = m1

        '使用获得的距离绘制圆形

        Dim m3 As New Mat(400, 400, DepthType.Cv8U, 3)

        m3.SetTo(New MCvScalar(0))

        CvInvoke.Rectangle(m3, New Rectangle(50, 50, 100, 100), New MCvScalar(255, 255, 255), -1)

        CvInvoke.Circle(m3, New Point(300, 300), 100, New MCvScalar(255, 255, 255), -1)

        CvInvoke.Circle(m3, p1, 2, New MCvScalar(0, 0, 255), -1)

        For i As Integer = 0 To dis.Count - 1

            CvInvoke.Circle(m3, p1, Math.Abs(dis(i)), New MCvScalar(0, 255, 0), 2)

        Next

        ImageBox2.Image = m3

End Sub

运行后如下图所示:

图6-14 点到轮廓的外接圆

上述代码只能获得最小距离,如果要得到轮廓外一点到轮廓最小距离的轮廓上一点的坐标,可以采用以下方法:

1、图像M1上绘制图形A

2、获得图形A的轮廓A(M1上只有一个轮廓)

3、获得点A到图形A的最小距离d

4、图像M2上使用点A为圆心,最小距离d为半径画圆A

5、M2和M1做异或,得到圆A

6、获得圆A的轮廓B(M2上只有一个圆形的轮廓)

7、获得轮廓B上的每个点到轮廓A的距离,判断是否符合条件:理论上等于0就表示该点在轮廓A上,但是通常不会直接判断=0而是给定一个范围。

那么符合条件的点即为需要的坐标点。

实现代码如下:

【代码位置:frmChapter6】Button14_Click

    '获得点到轮廓的最短距离

    '以点为圆心,最短距离为半径画圆

    '获得圆的轮廓上的点,这里可能会出现误差

    '求出每个点到轮廓的最短距离

    '如果为0,那么这个点在轮廓上,

    '但是通常而言,会有偏差

  '感觉此方法误差比较大

   Private Sub Button14_Click(sender As Object, e As EventArgs) Handles Button14.Click

        Dim m As New Mat(400, 400, DepthType.Cv8U, 1)

        m.SetTo(New MCvScalar(0))

        CvInvoke.Rectangle(m, New Rectangle(50, 50, 100, 100), New MCvScalar(255), -1)

        ImageBox1.Image = m

        Dim p1 As New Point(240, 100)

        Dim m1 As New Mat

        m1 = m.Clone

        '求出点到形状的距离

        Dim contours1 As New VectorOfVectorOfPoint

        CvInvoke.FindContours(m1, contours1, Nothing, RetrType.External, ChainApproxMethod.ChainApproxSimple)

        '这里只有一个形状轮廓,所以直接使用contours(0)

        Dim dis1 As Double = CvInvoke.PointPolygonTest(contours1(0), p1, True)

        '获得最短距离后画圆

        CvInvoke.Circle(m1, p1, Math.Abs(dis1), New MCvScalar(255), 1)

        ImageBox2.Image = m1

        'mm1异或,这里获得到刚才生成的圆形

        Dim m2 As New Mat

        CvInvoke.BitwiseXor(m, m1, m2)

        Dim contours2 As New VectorOfVectorOfPoint

        CvInvoke.FindContours(m2, contours2, Nothing, RetrType.External, ChainApproxMethod.ChainApproxSimple)

        '这里只有一个形状轮廓

        Dim cirpoints As VectorOfPoint = contours2(0)

        '保存形状上符合距离条件的点

        Dim shapes As New List(Of Point)

        For i As Integer = 0 To cirpoints.Size - 1

            Dim cirp As New Point(cirpoints(i).X, cirpoints(i).Y)

            '不用计算距离,只需要获得是否在轮廓上

            Dim dis As Double = CvInvoke.PointPolygonTest(contours1(0), cirp, True)

            '小于2视为符合条件

            If Math.Abs(dis) <= 1 Then

                shapes.Add(cirp)

            End If

        Next

        Dim m3 As New Mat

        m3 = m.Clone

        CvInvoke.CvtColor(m3, m3, ColorConversion.Gray2Bgr)

        '绘制点

        CvInvoke.Circle(m3, p1, 2, New MCvScalar(0, 0, 255), -1)

        '以点为圆心绘制圆,半径为最短距离

        CvInvoke.Circle(m3, p1, Math.Abs(dis1), New MCvScalar(0, 255, 0), 1)

        '画出线段

        For Each p As Point In shapes

            CvInvoke.Line(m3, p1, p, New MCvScalar(255, 0, 0), 1)

        Next

        ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-15 轮廓与轮廓外一点最小距离的坐标点

通过运行结果,可以看出此方法获得的坐标点太多,误差比较大,为此在下面的代码中进行改进,采用平均值来获得坐标点。

【代码位置:frmChapter6】Button15_Click

    '获得点到轮廓的最短距离

    '对上面代码上的改进,增加了平均值

    Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click

        Dim m As New Mat(400, 400, DepthType.Cv8U, 1)

        m.SetTo(New MCvScalar(0))

        'CvInvoke.Circle(m, New Point(300, 300), 100, New MCvScalar(255), -1)

        CvInvoke.Rectangle(m, New Rectangle(50, 50, 100, 100), New MCvScalar(255), -1)

        ImageBox1.Image = m

        Dim p1 As New Point(240, 100)

        Dim m1 As New Mat

        m1 = m.Clone

        '求出点到形状的距离

        Dim contours As New VectorOfVectorOfPoint

        CvInvoke.FindContours(m1, contours, Nothing, RetrType.External, ChainApproxMethod.ChainApproxSimple)

        '这里只有一个形状轮廓

        Dim dis1 As Double = CvInvoke.PointPolygonTest(contours(0), p1, True)

        CvInvoke.Circle(m1, p1, Math.Abs(dis1), New MCvScalar(255), 1)

        ImageBox2.Image = m1

        Dim m2 As New Mat

        CvInvoke.BitwiseXor(m, m1, m2)

        'ImageBox3.Image = m2

        Dim contours1 As New VectorOfVectorOfPoint

        CvInvoke.FindContours(m2, contours1, Nothing, RetrType.External, ChainApproxMethod.ChainApproxSimple)

        '这里只有一个形状轮廓

        Dim cirpoints As VectorOfPoint = contours1(0)

        Dim shapes As New List(Of Point)

        For i As Integer = 0 To cirpoints.Size - 1

            Dim cirp As New Point(cirpoints(i).X, cirpoints(i).Y)

            '不用计算距离,只需要获得是否在轮廓上

            Dim dis As Double = CvInvoke.PointPolygonTest(contours(0), cirp, True)

            '距离是否在设置范围,这里是3,多少都没所谓,后面要计算平均值

            If Math.Abs(dis) <= 3 Then

                shapes.Add(cirp)

            End If

        Next

        Dim m3 As New Mat

        m3 = m.Clone

        CvInvoke.CvtColor(m3, m3, ColorConversion.Gray2Bgr)

        CvInvoke.Circle(m3, p1, Math.Abs(dis1), New MCvScalar(0, 255, 0), 1)

        CvInvoke.Circle(m3, p1, 2, New MCvScalar(0, 0, 255), -1)

        Dim totalx As Double = 0

        Dim totaly As Double = 0

        Dim avgx As Double

        Dim avgy As Double

        '平均值计算点坐标

        For i As Integer = 0 To shapes.Count - 1

            totalx += shapes(i).X

            totaly += shapes(i).Y

        Next

        avgx = totalx / shapes.Count

        avgy = totaly / shapes.Count

        CvInvoke.Line(m3, p1, New Point(CInt(avgx), CInt(avgy)), New MCvScalar(255, 0, 0), 1)

        ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-16 轮廓与轮廓外一点最小距离的坐标点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2065755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聚类分析|距离与相似系数|层次聚类|K均值聚类|SPSS及Matlab

聚类分析问题描述 聚类分析问题描述 人类认识世界的方法之一就是将事物按照各种属性或特征分成若干类别。 物以类聚、人以群分。分类方法多种多样&#xff0c;简单直接的如高、矮、胖瘦。使用的信息量小&#xff0c;但对类别界限附近的案例&#xff0c;分类结果不一定合适。 …

Linux 命令管道介绍

今天给伙伴们分享一下Linux 命令管道&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路上得到支持和共同进步&am…

软考:软件设计师 — 15.数据结构及算法应用

十五. 数据结构及算法应用 数据结构及算法应用类题目是下午场考试中的第四道题目&#xff0c;分值 15 分&#xff0c;主要以 C 语言填空、算法策略判断和时间复杂度判断为考察形式&#xff0c;建议拿到 6 分以上。 1. 解题技巧 算法策略与时间复杂度部分详细内容可以参考文章…

测试干货 | 如何选择合适的半导体检测方法?看完这篇就明白了!

撰文排版&#xff1a;刘佳 审核指导&#xff1a;肖俊灵 本文较长&#xff0c;建议先收藏后随时查看&#xff01;以后我们将更新更多此类硬核科普&#xff0c;欢迎关注&#xff01; 半导体材料作为半导体产业链中的重要支撑&#xff0c;包括以硅、锗等为代表的元素半导体材料和以…

图与树的基本概念

目录 引言 图与树结构的重要性 图的基本概念 图的表示方式 图的遍历算法 树的基本概念 树的定义与性质 树的遍历 二叉树与多叉树的概念 图与树的高级应用 最短路径算法 最小生成树算法 总结与应用 综合实例分析 引言 在计算机科学的世界中&#xff0c;图和树是两…

商圈停车泊位实时查询与推荐系统 项目编号:17259(案例分享)

摘 要 在当今城市化进程加快的背景下&#xff0c;城市停车问题日益突出&#xff0c;给市民出行带来诸多不便。为解决停车难题&#xff0c;提高停车效率&#xff0c;基于Java开发语言和Spring Boot框架&#xff0c;结合MySQL数据库技术&#xff0c;开发了商圈停车泊位实时查询…

计算机Java项目|基于SpringBoot的网络海鲜市场系统的设计与实现

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参…

牛客小白月赛96

牛客小白月赛96 A 最少胜利题数 链接&#xff1a;https://ac.nowcoder.com/acm/contest/84528/A 来源&#xff1a;牛客网 题目描述 本场小白月赛共 6 题&#xff0c;&#x1d435;&#x1d456;&#x1d45b;&#x1d454;&#x1d44f;&#x1d45c;&#x1d45b;&#x1d4…

【hot100篇-python刷题记录】【找到字符串中所有字母异位词】

R6-滑动窗口篇 印象题 核心&#xff1a; 使用collections方法的Counter计数&#xff0c;统计了某个子串中每个字母出现的次数。 判断子串相等&#xff1a;counter1counter2 &#xff08;注意&#xff1a;此时&#xff0c;counter1或者counter2都不能含有多余的项&#xff0…

JVM系列--初始JVM

根据《黑马程序员JVM虚拟机入门到实战全套视频教程》整理 1 什么是JVM JVM 全称是 Java Virtual Machine&#xff0c;中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 Java源代码执行流程如下&#xff1a; 分为三个步…

Mysql 集群技术

一、Mysql 在服务器中的部署方法 在企业中90%的服务器操作系统均为Linux在企业中对于Mysql的安装通常用源码编译的方式来进行官网&#xff1a;http://www.mysql.com 1.1 在Linux下部署mysql cmake \ -DCMAKE_INSTALL_PREFIX/usr/local/mysql \ #指定安装路径 -DMYSQL_DATADI…

【Unity变现】Unity 接入Unity ADS广告

说在前面的话&#xff0c;Unity ADS是Unity官方做的广告变现平台&#xff0c;但广告在我国大陆无法使用&#xff0c;开发时测试的话需要上代理才能看到请求的广告。 如果游戏不准备发布到海外市场&#xff0c;可以不考虑这个平台。 一、注册Unity ADS平台的准备 https://dash…

JavaEE 第17节 网络通信知识扫盲

文章目录 前言一、网络通信的概念二、局域网&广域网 局域网&#xff08;LAN&#xff0c;Local Area Network&#xff09; 广域网 三、IP地址与端口号 1、IP地址 2、端口号 四、网络协议 1、概念&作用 2、协议分层&#xff08;重要&#xff09; 前言 此篇博…

你是如何更精准地指引模型,激发其无尽的创造力?

随着大型语言模型日益凸显其重要性&#xff0c;发掘并充分利用它们的潜力&#xff0c;很大程度上依赖于我们如何巧妙构思和构造指令——即Prompt的精炼艺术。优化Prompt撰写技巧&#xff0c;将能够更好地引导大模型&#xff0c;为各类应用场景生成高质量的文本输出。分享出你的…

CTF杂项题:easy_nbt writeup

题目 题目如图&#xff0c;有一个附件&#xff1a;file.7z 解题思路 CTF的杂项题&#xff0c;对于刚接触的人员来说&#xff0c;很多时候是完全没有思路&#xff0c;解这类题&#xff0c;没有相关知识储备的时候&#xff0c;可以使用文件内容搜索工具搜索flag、ctf、key等关键…

【实现100个unity特效之25】Unity中实现二次元模型,基于光照的内置和URP管线卡通化渲染shader

最终效果 文章目录 最终效果默认效果简单粗暴&#xff0c;使用Unlit/Texture基于光照模型的卡通渲染UnityToonShader——仅支持内置渲染管线基于光照模型的二次元渲染UnityURPToonLitShaderExample——仅支持URP渲染管线 完结 默认效果 不然不做处理&#xff0c;我们的模型默认…

高并发eleme项目登录模块(thirty-three day)

一、配置一主二从mysql 1. mycat对mysql8不完全支持 2. mysql8主从问题不大get_pub_key1 3. gtids事务复制 4. 删除/etc/my.cnf 5. 同步data文件需要先停用mysql服务,删除data目录中的auto.cnf 6. gtid模式以及经典模式都需要锁表 flush tables with read lock; unlock …

怎么用电脑兼职赚钱,普通人可做的6个副业项目(非常详细)零基础入门到精通,收藏这篇就够了

现在的生活中&#xff0c;我们总是感觉所过的日子都很紧张&#xff0c;虽然我们尽可能地工作和努力&#xff0c;但是生活成本和社会压力仍然那么大。为了弥补自己的生活经验和财务困难&#xff0c;很多人开始寻找一种额外的收入来源。 其实这种额外的收入来源就被称之为&#…

google paly修改地区教程【2024自测可用】

【准备信息】 https://usfakename.com/ &#xff1a; 用来生成其他国家&#xff08;比如美国&#xff09;的地址 重要需要填写的内容&#xff1a; 卡号&#xff1a;4532 7875 1109 8437 City:Boulder State:Alabama postcode:35259 可以在美国邮政编码ZIP Code(转载) -…

学习yolo+Java+opencv简单案例(一)

目录 一、大概架构 二、编写pom.xml 1、yolo-study模块&#xff08;root&#xff09;&#xff1a; 2、CameraDetection模块 三、编写yml配置文件 四、编写controller 五&#xff0c;可能会出现的问题 1、修改VM启动参数&#xff1a; 2、修改启动类 六、测试 七&…