版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
教程VB.net版本请访问: EmguCV学习笔记 VB.Net 目录-CSDN博客
教程C#版本请访问: EmguCV学习笔记 C# 目录-CSDN博客
笔者的博客网址:https://blog.csdn.net/uruseibest
教程配套文件及相关说明以及如何获得pdf教程和代码(博客上的教程内容会和pdf教程一致,教程中也会包含所有代码),请移步:************************************************************************************************************************************************************************************************************************************************************EmguCV学习笔记****************************************************************************************************************************************************************************************************************************************************************
4.4 图像形态学
图像形态学是数字图像处理中的一种重要技术,它主要用于对二值图像进行分析和处理。图像形态学可以用于图像去噪、边缘检测、形态分析等方面。EmguCV提供了一系列的图像形态学操作函数,包括膨胀、腐蚀、开运算、闭运算等。
- 膨胀 (Dilation)
膨胀是一种形态学操作,其基本思想是用一个结构元素 (Structuring Element) 在图像上滑动,将结构元素包含的像素值中的最大值作为当前像素值,从而实现对图像边缘的扩张和增强。EmguCV中的膨胀函数为CvInvoke.Dilate。
- 腐蚀 (Erosion)
腐蚀是一种形态学操作,其基本思想是用一个结构元素在图像上滑动,将结构元素包含的像素值中的最小值作为当前像素值,从而实现对图像边缘的收缩和平滑。EmguCV中的腐蚀函数为CvInvoke.Erode。
- 开运算 (Opening)
开运算是一种形态学操作,其基本思想是先进行一次腐蚀操作,再进行一次膨胀操作,从而可以去除比较小的物体、断开细长的物体等。EmguCV中的开运算函数为CvInvoke.MorphologyEx,其类型为MorphOp.Open。
- 闭运算 (Closing)
闭运算是一种形态学操作,其基本思想是先进行一次膨胀操作,再进行一次腐蚀操作,从而可以填充物体内的小孔、连接断开的物体等。EmguCV中的闭运算函数为CvInvoke.MorphologyEx,其类型为MorphOp.Close。
图像形态学操作需要根据图像的特点和处理目的进行合理的选择和组合,才能达到良好的效果。
**注意:**图像形态学针对的是非黑色部分(非0部分)操作。
4.4.1 GetStructuringElement
通过CvInvoke.GetStructuringElement方法可以创建形态学操作的结构元素。该方法返回一个Mat对象。定义如下:
Public Shared Function GetStructuringElement(shape As Emgu.CV.CvEnum.ElementShape, ksize As System.Drawing.Size, anchor As System.Drawing.Point) As Emgu.CV.Mat
参数说明:
- shape:结构元素的形状,可以是Rectangle(矩形)、Cross(十字形)、Ellipse(椭圆形)。
- size:结构元素的大小。
- anchor:结构元素的锚点位置,用Point结构指定。可以使用 Nothing 或者(-1,-1),表示将锚点放置在结构元素的中心。
下面的代码创建了一个3x3的十字形结构元素:
Dim element As Mat
element= CvInvoke.GetStructuringElement(ElementShape.Cross, New Size(3, 3))
4.4.2 Erode
Erode方法对图像进行腐蚀操作,该方法声明如下:
Public Shared Sub Erode(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, element As Emgu.CV.IInputArray, anchor As System.Drawing.Point, iterations As Integer, borderType As Emgu.CV.CvEnum.BorderType, borderValue As Emgu.CV.Structure.MCvScalar)
参数说明:
- element:结构元素。
- anchor:结构元素的锚点位置,类型为Point。指定结构元素的锚点位置,一般为结构元素的中心,即(-1,-1)。
- iterations:腐蚀操作的迭代次数,类型为Integer。默认为1,表示进行一次腐蚀操作。
- Iterations:操作的迭代次数,类型为Integer。默认为1,表示进行一次膨胀操作。
- borderType:边界处理方式,类型为BorderType(详见4.2.1节【BorderType】)。需要注意的是,使用的BorderType类型不同生成结果不同。
- borderValue:边界值,类型为MCvScalar。当borderType为BorderType.Constant时,可以指定边界的像素值。通常设置为Nothing。
【代码位置:frmChapter4】Button12_Click、printMatByte
'Erode腐蚀
Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click
'创建结构元素,这里是一个3*3大小的十字形结构
Dim kernel As New Mat
kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
Dim bte1(,) As Byte
bte1 = {
{0, 1, 1, 1, 1, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 1, 1, 1, 1, 0}
}
Dim matr1 As New Matrix(Of Byte)(bte1)
Dim m1 As New Mat
m1 = matr1.Mat
Dim merode As New Mat '
'这里使用了2次迭代
CvInvoke.Erode(m1, merode, kernel, New Point(-1, -1), 2, BorderType.Constant, Nothing)
Call printMatByte(merode)
End Sub
'输出Mat的值
Private Sub printMatByte(ByVal m As Mat)
Dim matr As New Matrix(Of Byte)(m.Rows, m.Cols, m.NumberOfChannels)
m.CopyTo(matr)
For i As Integer = 0 To matr.Rows - 1
For j As Integer = 0 To matr.Cols - 1
Console.Write(matr(i, j))
If j <> matr.Cols - 1 Then
Console.Write(",")
End If
Next
Console.WriteLine()
Next
End Sub
下图演示了使用腐蚀进行2次迭代的结果:
图4-12 进行二次腐蚀的情况
4.4.3 Dilate
Dilate方法对图像进行膨胀操作,该方法声明如下:
Public Shared Sub Dilate(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, element As Emgu.CV.IInputArray, anchor As System.Drawing.Point, iterations As Integer, borderType As Emgu.CV.CvEnum.BorderType, borderValue As Emgu.CV.Structure.MCvScalar)
参数请参看4.3.2节【Erode】中的介绍。
【代码位置:frmChapter4】Button13_Click
'Dilate 膨胀
Private Sub Button13_Click(sender As Object, e As EventArgs) Handles Button13.Click
'创建结构元素,这里是一个3*3大小的十字形结构
Dim kernel As New Mat
kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
Dim bte2(,) As Byte
bte2 = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
}
Dim matr2 As New Matrix(Of Byte)(bte2)
Dim m2 As New Mat
m2 = matr2.Mat
Dim mdilate As New Mat
'这里使用了2次迭代进行膨胀
CvInvoke.Dilate(m2, mdilate, kernel, New Point(-1, -1), 2, BorderType.Constant, Nothing)
Call printMatByte(mdilate)
End Sub
下图演示了使用腐蚀进行2次迭代的结果:
图4-13 进行二次膨胀的情况
以下代码演示了使用腐蚀和膨胀来处理图像。
【代码位置:frmChapter4】Button14_Click
'Erode和Dilate
Private Sub Button14_Click(sender As Object, e As EventArgs) Handles Button14.Click
Dim m As Mat = CvInvoke.Imread("C:\lessons\lena.jpg", CvEnum.ImreadModes.Color)
ImageBox1.Image = m
Dim mElement As New Mat
mElement = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
'腐蚀
Dim mout1 As New Mat
CvInvoke.Erode(m, mout1, mElement, New Point(-1, -1), 2, BorderType.Default, Nothing)
ImageBox2.Image = mout1
'膨胀
Dim mout2 As New Mat
CvInvoke.Dilate(m, mout2, mElement, New Point(-1, -1), 2, BorderType.Default, Nothing)
ImageBox3.Image = mout2
End Sub
运行后如下图所示:
图4-14 使用腐蚀和膨胀处理图像
4.4.4 MorphologyEx
为了实现更多图像形态学操作,EmguCV提供了CvInvoke.MorphologyEx方法,声明如下:
Public Shared Sub MorphologyEx(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, operation As Emgu.CV.CvEnum.MorphOp, kernel As Emgu.CV.IInputArray, anchor As System.Drawing.Point, iterations As Integer, borderType As Emgu.CV.CvEnum.BorderType, borderValue As Emgu.CV.Structure.MCvScalar)
参数说明,其余参数请参看4.3.2节【Erode】中的介绍:
- operation:形态学操作类型,类型为MorphOp,包括以下几种形态学操作:
- Dilate:膨胀操作,
- Erode:腐蚀操作。
- Open:开运算,先进行腐蚀再进行膨胀,可以用于去除小的噪点和连接断开的区域。
- Close:闭运算,先进行膨胀再进行腐蚀,可以用于填充小的空洞和分离连接的区域。
- Gradient:梯度运算,用膨胀图像减去腐蚀图像,可以得到图像边缘。
- TopHat:高帽运算,用原始图像减去开运算后的图像,可以提取图像中的亮点或小的细节信息。
- BlackHat:低帽运算,用闭运算后的图像减去原始图像,可以提取图像中的暗点或背景信息。
- HitMiss:击中击不中运算,用于确定图像中是否存在指定的形状。它需要两个结构元素:一个前景结构元素和一个背景结构元素。在输入图像上,如果前景结构元素可以同时与前景像素和背景像素匹配,那么该像素属于击中集合;否则,它属于击不中集合。通过对击中集合进行膨胀操作并减去原始击中集合得到最终结果。
以下代码演示了使用开运算来处理图像数据,同时与腐蚀,膨胀操作图像数据做对比。
【代码位置:frmChapter4】Button15_Click
'MorphologyEx:开运算:先腐蚀,再膨胀
Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click
Dim bte(,) As Byte
bte = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 0, 0, 0, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
}
Dim matr As New Matrix(Of Byte)(bte)
Dim m As New Mat
m = matr.Mat
'创建结构元素,这里是一个3*3大小的十字形结构
Dim kernel As New Mat
kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
'进行开运算
Dim mMorphology As New Mat
CvInvoke.MorphologyEx(m, mMorphology, MorphOp.Open, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(mMorphology)
Console.WriteLine("===============================")
'先腐蚀
Dim merode As New Mat
CvInvoke.Erode(m, merode, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(merode)
Console.WriteLine("===============================")
'再膨胀
Dim mdilate As New Mat
CvInvoke.Dilate(merode, mdilate, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(mdilate)
End Sub
下图演示了使用开运算处理图像数据的结果:
图4-15 开运算处理图像数据
以下代码演示了使用闭运算来处理图像数据,同时与膨胀,腐蚀操作图像数据做对比。
【代码位置:frmChapter4】Button16_Click
'MorphologyEx:闭运算:先膨胀,再腐蚀
Private Sub Button16_Click(sender As Object, e As EventArgs) Handles Button16.Click
Dim bte(,) As Byte
bte = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 0, 1, 1, 1, 0},
{0, 1, 1, 1, 0, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 0, 1, 1, 1, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
}
Dim matr As New Matrix(Of Byte)(bte)
Dim m As New Mat
m = matr.Mat
'创建结构元素,这里是一个3*3大小的十字形结构
Dim kernel As New Mat
kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
'闭运算
Dim mMorphology As New Mat
CvInvoke.MorphologyEx(m, mMorphology, MorphOp.Close, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(mMorphology)
Console.WriteLine("===============================")
'先膨胀
Dim mdilate As New Mat
CvInvoke.Dilate(m, mdilate, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(mdilate)
Console.WriteLine("===============================")
'再腐蚀
Dim merode As New Mat
CvInvoke.Erode(mdilate, merode, kernel, New Point(-1, -1), 1, BorderType.Constant, Nothing)
Call printMatByte(merode)
End Sub
下图演示了使用闭运算处理图像数据的结果:
图4-16 闭运算处理图像数据
以下代码演示了使用闭运算和开运算来处理图像。
【代码位置:frmChapter4】Button17_Click
'MorphologyEx:开运算和闭运算处理图像
Private Sub Button17_Click(sender As Object, e As EventArgs) Handles Button17.Click
Dim m As Mat = CvInvoke.Imread("C:\lessons\lena.jpg", CvEnum.ImreadModes.Color)
ImageBox1.Image = m
Dim mElement As New Mat
mElement = CvInvoke.GetStructuringElement(ElementShape.Cross, New Drawing.Size(3, 3), New Point(-1, -1))
'开运算
Dim mout1 As New Mat
CvInvoke.MorphologyEx(m, mout1, MorphOp.Open, mElement, New Point(-1, -1), 3, BorderType.Default, New MCvScalar(0, 0, 0))
ImageBox2.Image = mout1
'闭运算
Dim mout2 As New Mat
CvInvoke.MorphologyEx(m, mout2, MorphOp.Close, mElement, New Point(-1, -1), 3, BorderType.Default, New MCvScalar(0, 0, 0))
ImageBox3.Image = mout2
End Sub
运行后如下图所示:
图4-17 开运算和闭运算处理图像