EmguCV学习笔记 VB.Net 6.4 霍夫变换

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

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.4 霍夫变换

霍夫变换(Hough Transform)是一种在图像中检测几何形状的常用方法,最初用于检测直线,后来也扩展到检测其他形状,如圆、椭圆等。霍夫变换的核心思想是将图像空间中的特征点映射到参数空间中,并通过在参数空间中寻找峰值来检测形状。

霍夫变换的优点是对于图像中的形状检测具有较好的鲁棒性,对于存在噪声和遮挡的情况仍能有效检测。然而,它的计算复杂度较高,对于大型图像或复杂形状的检测可能会消耗较多的计算资源。

在Emgu.CV中,霍夫变换相关的函数有CvInvoke.HoughLinesP用于检测直线线段,CvInvoke.HoughLines用于直线检测,CvInvoke.HoughCircles用于圆检测等。这些函数可以方便地在图像中进行霍夫变换来检测不同形状的目标。

6.4.1 HoughLines

CvInvoke.HoughLines方法用于在图像中检测直线。该函数会返回检测到的直线的参数。该方法声明如下:

Public Shared Sub HoughLines(image As Emgu.CV.IInputArray, lines As Emgu.CV.IOutputArray, rho As Double, theta As Double, threshold As Integer, Optional srn As Double = 0, Optional stn As Double = 0)

参数说明:

  1. Image:输入源图像(一般为8位单通道二值图像)。
  2. lines:经过霍夫变换后检测线条的输出矢量。这里传入VectorOfPointF类型变量。返回的每一条线由两个元素的矢量(ρ, θ)表示, 其中ρ是离坐标原点的距离, θ是弧度线条旋转角度(0表示垂直线, n / 2度表示水平线)。
  3. rho:以像素为单位的距离精度, 可以认为是直线搜索时的步进尺寸的单位半径。
  4. theta:以弧度为单位的角度精度, 可以认为是直线搜索时的步进尺寸的角度单位,常设为 Math.PI / 180。
  5. threshold:直线检测的阈值,只有当检测到的点数大于该阈值时才认为是直线。
  6. srn:控制距离分辨率。将距离分辨率除以srn+1,从而减小距离分辨率。其默认值为0。该参数的值越大,累加器空间的距离分辨率就越低,检测到的直线数量也会相应地减少。
  7. stn:控制角度分辨率。将角度分辨率除以stn+1,从而减小角度分辨率。其默认值为0。该参数的值越大,累加器空间的角度分辨率就越低,检测到的直线数量也会相应地减少。

【代码位置:frmChapter6】Button16_Click

'HoughLines

Private Sub Button16_Click(sender As Object, e As EventArgs) Handles Button16.Click

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

'边缘检测

Dim mid1 As New Mat

CvInvoke.Canny(m1, mid1, 80, 255, 3)

'二值化

Dim mid2 As New Mat

CvInvoke.Threshold(mid1, mid2, 125, 255, ThresholdType.Binary)

ImageBox1.Image = mid2

'HoughLines检测直线

Dim outlines As New VectorOfPointF

CvInvoke.HoughLines(mid2, outlines, 1, Math.PI / 180, 250, 0, 0)

Dim m2 As New Mat

m2 = mid1.Clone()

m2.SetTo(New MCvScalar(0))

'计算每条直线的起始坐标,并绘制出来

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

Dim line As PointF = outlines(i)

Dim rho As Double = line.X

Dim theta As Double = line.Y

Dim a As Double = Math.Cos(theta)

Dim b As Double = Math.Sin(theta)

Dim x0 As Double = rho * a

Dim y0 As Double = rho * b

Dim pt1 As New Point

pt1.X = Math.Round(x0 + m2.Cols * (-b))

pt1.Y = Math.Round(y0 + m2.Rows * a)

Dim pt2 As New Point

pt2.X = Math.Round(x0 - m2.Cols * (-b))

pt2.Y = Math.Round(y0 - m2.Rows * a)

'绘制直线

CvInvoke.Line(m2, pt1, pt2, New MCvScalar(255), 2)

Next

ImageBox2.Image = m2

'减少检测到的点数

Dim outlines3 As New VectorOfPointF

CvInvoke.HoughLines(mid2, outlines3, 1, Math.PI / 180, 120, 0, 0)

Dim m3 As New Mat

m3 = mid1.Clone()

m3.SetTo(New MCvScalar(0))

Dim length3 As Double = Math.Max(m3.Rows, m3.Cols)

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

Dim line As PointF = outlines3(i)

Dim rho As Double = line.X

Dim theta As Double = line.Y

Dim a As Double = Math.Cos(theta)

Dim b As Double = Math.Sin(theta)

Dim x0 As Double = rho * a

Dim y0 As Double = rho * b

Dim pt1 As New Point

pt1.X = Math.Round(x0 + m2.Cols * (-b))

pt1.Y = Math.Round(y0 + m2.Rows * a)

Dim pt2 As New Point

pt2.X = Math.Round(x0 - m2.Cols * (-b))

pt2.Y = Math.Round(y0 - m2.Rows * a)

CvInvoke.Line(m3, pt1, pt2, New MCvScalar(255), 2)

Next

ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-17 直线检测结果

6.4.2 HoughLinesP

CvInvoke.HoughLinesP方法用于在图像中检测线段。该方法的两个声明如下:

Public Shared Sub HoughLinesP(image As Emgu.CV.IInputArray, lines As Emgu.CV.IOutputArray, rho As Double, theta As Double, threshold As Integer, Optional minLineLength As Double = 0, Optional maxGap As Double = 0)

Public Shared Function HoughLinesP(image As Emgu.CV.IInputArray, rho As Double, theta As Double, threshold As Integer, Optional minLineLength As Double = 0, Optional maxGap As Double = 0) As Emgu.CV.Structure.LineSegment2D()

参数解释:

  1. image:输入图像(Image(Of Gray, Byte)类型)。
  2. lines:经过霍夫变换后检测线条的输出矢量。VectorOfRect类型,每个成员是一个Rectangle类型,属性X 、Y、Width、Height分别表示第一个点的X、第一个点的Y,第二个点的X、第二个点的Y。
  3. rho:以像素为单位的距离精度。
  4. theta:以弧度为单位的角度精度。
  5. threshold:直线检测的阈值,只有当检测到的点数大于该阈值时才认为是直线。
  6. minLineLength:线段的最小长度,小于该长度的线段将被忽略。
  7. maxLineGap:线段之间的最大间隔,超过该间隔的线段将被认为是不同的线段。

返回值:

检测到的线段数组(LineSegment2D()类型)。

【代码位置:frmChapter6】Button17_Click

'HoughLinesP

Private Sub Button17_Click(sender As Object, e As EventArgs) Handles Button17.Click

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

'边缘检测

Dim mid1 As New Mat

CvInvoke.Canny(m1, mid1, 80, 255, 3)

'二值化

Dim mid2 As New Mat

CvInvoke.Threshold(mid1, mid2, 125, 255, ThresholdType.Binary)

ImageBox1.Image = mid2

Dim outlines() As LineSegment2D

outlines = CvInvoke.HoughLinesP(mid2, 1, Math.PI / 180, 100, 0, 0)

Dim m2 As New Mat

m2 = mid1.Clone()

m2.SetTo(New MCvScalar(0))

'绘制检测出的线段

For i As Integer = 0 To outlines.Length - 1

CvInvoke.Line(m2, outlines(i).P1, outlines(i).P2, New MCvScalar(255), 2)

Next

ImageBox2.Image = m2

Dim outlines2 As New VectorOfRect()

CvInvoke.HoughLinesP(mid2, outlines2, 1, Math.PI / 180, 100, 5, 30)

Dim m3 As New Mat

m3 = mid1.Clone()

m3.SetTo(New MCvScalar(0))

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

CvInvoke.Line(m3, New Point(outlines2(i).X, outlines2(i).Y), New Point(outlines2(i).Width, outlines2(i).Height), New MCvScalar(255), 2)

Next

ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-18 线段检测结果

6.4.3 HoughCircles

CvInvoke.HoughCircles函数用于在图像中检测圆形,该方法声明如下:

Public Shared Function HoughCircles(image As Emgu.CV.IInputArray, method As Emgu.CV.CvEnum.HoughModes, dp As Double, minDist As Double, Optional param1 As Double = 100, Optional param2 As Double = 100, Optional minRadius As Integer = 0, Optional maxRadius As Integer = 0) As Emgu.CV.Structure.CircleF()

参数说明:

  1. image:8位单通道灰度源图像(或者传入的源图像是Image(Of Gray, Byte)类型)。
  2. method:霍夫变换的方法,可以选择HoughType.Gradient或HoughType.GradientAlt。
  3. dp:累加器图像的分辨率与输入图像的分辨率之比。例如,dp = 1,则累加器具有与输入图像相同的分辨率。如果dp = 2,则累加器的宽度和高度都是一半。
  4. minDist:检测到的圆心之间的最小距离,太小会多检,太大会漏检。
  5. param1:Canny边缘检测的高阈值。
  6. param2:圆心累加器阈值,只有当累加器图像中的值大于该阈值时才认为是圆心。相应的该阈值越小,可得到越多的圆。
  7. minRadius:达到检测要求的最小圆半径。
  8. maxRadius:达到检测要求的最大圆半径。

返回值:

检测到的圆形数组(CircleF()类型)。

【代码位置:frmChapter6】Button18_Click

'HoughCircles

Private Sub Button18_Click(sender As Object, e As EventArgs) Handles Button18.Click

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

ImageBox1.Image = m1

Dim mid1 As New Mat

CvInvoke.GaussianBlur(m1, mid1, New Drawing.Size(3, 3), 3)

ImageBox2.Image = mid1

Dim outcircle() As CircleF

outcircle = CvInvoke.HoughCircles(mid1, HoughModes.Gradient, 2, 50, 140, 220, 5)

Dim m2 As New Mat

m2 = mid1.Clone()

m2.SetTo(New MCvScalar(255))

For i As Integer = 0 To outcircle.Length - 1

CvInvoke.Circle(m2, New Point(Integer.Parse(outcircle(i).Center.X), Integer.Parse(outcircle(i).Center.Y)), outcircle(i).Radius, New MCvScalar(0), 2)

Next

ImageBox3.Image = m2

End Sub

运行后如下图所示:

图6-19 圆形检测结果

另外一个例子,代码同上,只是载入的图片不同:

【代码位置:frmChapter6】Button19_Click

......

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

......

运行后如下图所示:

图6-20 圆形检测结果

相关推荐
向宇it6 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
数据的世界016 小时前
.NET开发人员学习书籍推荐
学习·.net
菜狗woc7 小时前
opencv-python的简单练习
人工智能·python·opencv
向宇it8 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
paixiaoxin8 小时前
CV-OCR经典论文解读|An Empirical Study of Scaling Law for OCR/OCR 缩放定律的实证研究
人工智能·深度学习·机器学习·生成对抗网络·计算机视觉·ocr·.net
西猫雷婶9 小时前
python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分
开发语言·python·opencv
AI视觉网奇9 小时前
人脸生成3d模型 Era3D
人工智能·计算机视觉
云空9 小时前
《QT 5.14.1 搭建 opencv 环境全攻略》
开发语言·qt·opencv
编码小哥9 小时前
opencv中的色彩空间
opencv·计算机视觉
吃个糖糖9 小时前
34 Opencv 自定义角点检测
人工智能·opencv·计算机视觉