版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
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博客
11.5 目标检测
11.5.1 Yolo
YOLO(You Only Look Once)是一种流行的目标检测算法,它使用单个神经网络同时进行对象检测和对象分类。相比于传统的目标检测算法,YOLO在目标检测任务中表现优秀,有更快的速度和更高的准确性,被广泛应用于自动驾驶、安防监控等领域。
【代码位置:frmChapter11】Button3_Click
'目标检测:yolo
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
'对象分类,coco.names文件提供了80类对象
Dim classnames() As String
classnames = File.ReadAllLines("C:\learnEmgucv\yolo\coco.names")
'需要测试的图像文件
Dim m As New Mat("C:\learnEmgucv\dnntest.jpg", ImreadModes.Color)
Dim hm As Integer = m.Height
Dim wm As Integer = m.Width
Dim net As Dnn.Net
'读取yolo的推理模型文件
net = DnnInvoke.ReadNetFromDarknet("C:\learnEmgucv\yolo\yolov3.cfg", "C:\learnEmgucv\yolo\yolov3.weights")
net.SetPreferableBackend(Dnn.Backend.OpenCV)
net.SetPreferableTarget(Target.Cpu)
Dim blob As Mat
'注意:BlobFromImage的size参数
'以前使用(416,416),现在是(608, 608),参看yolov3.cfg。
'如果继续使用(416,416),那么会有部分物体检测不出
blob = DnnInvoke.BlobFromImage(m, 1.0 / 255.0, New Size(608, 608), New MCvScalar(0, 0, 0), True, False)
net.SetInput(blob)
'获取推理模型中未连接的输出层名称列表
Dim names() As String = net.UnconnectedOutLayersNames
'或者以下方法获得
'Dim outLayers() As Integer = net.UnconnectedOutLayers ''
'Dim layerNames() As String = net.LayerNames
'Dim names(outLayers.Length - 1) As String
'For i As Integer = 0 To outLayers.Length - 1
' names(i) = layerNames(outLayers(i) - 1)
'Next
Dim mout As New VectorOfMat
net.Forward(mout, names)
'只有一张图片,只需要mout(0)即可
Dim mout1 As New Mat
mout1 = mout(0)
'返回二维数组
Dim detection(,) As Single
detection = mout1.GetData()
Dim rows As Integer = detection.GetLength(0)
Dim cols As Integer = detection.GetLength(1)
'置信度
Dim lstYoloConf As New List(Of Single)
'方框坐标
Dim lstYoloRects As New List(Of Rectangle)
'识别到的物体序号
Dim lstYoloIndex As New List(Of Integer)
'行数为检测出对象的数量
'每列从 0 到 84,一共85个元素,
' 0-1为矩形区域的中心坐标X和Y的百分比
' 2-3为矩形的宽度和高度的百分比
' 4为矩形区域的置信度
' 5-84为对应的80类对象分别的置信度
'存在两个置信度
For i As Integer = 0 To rows - 1
'第一个置信度是矩形区域的置信度
Dim conf As Single = detection(i, 4)
'先判断矩形区域的置信度是否符合要求
If conf > 0.5 Then
Dim x As Single = detection(i, 0) * wm '百分比,需要乘以源图像的宽度
Dim y As Single = detection(i, 1) * hm '百分比,需要乘以源图像的高度
Dim w As Single = detection(i, 2) * wm '百分比,需要乘以源图像的宽度
Dim h As Single = detection(i, 3) * hm '百分比,需要乘以源图像的高度
For k As Integer = 5 To 84
'第二个置信度是检测出的对象分类的置信度
'判断对象分类的置信度是否符合要求
If detection(i, k) > 0.5 Then
lstYoloConf.Add(conf)
lstYoloRects.Add(New Rectangle(CInt(x - w / 2), CInt(y - h / 2), w, h))
'注意,是从第6个(索引为5)开始
lstYoloIndex.Add(k - 5)
End If
Next
End If
Next
'利用NMS把重复位置的rectangle去除
Dim selectedObj() As Integer
selectedObj = DnnInvoke.NMSBoxes(lstYoloRects.ToArray, lstYoloConf.ToArray, 0.2F, 0.3F)
For i As Integer = 0 To lstYoloRects.Count - 1
'只画出被保留下來的rectangle
If (selectedObj.Contains(i)) Then
'输出检测出的对象所在矩形区域
CvInvoke.Rectangle(m, lstYoloRects(i), New MCvScalar(0, 255, 0), 1)
'获得检测出的对象的种类名称
Dim objName As String
objName = classnames(lstYoloIndex(i))
'输出检测出的对象名称
CvInvoke.PutText(m, objName,
New Point(lstYoloRects(i).X, lstYoloRects(i).Y - 5),
FontFace.HersheyTriplex, 0.3, New MCvScalar(0, 0, 255))
'输出检测出的置信度
CvInvoke.PutText(m, lstYoloConf(i),
New Point(lstYoloRects(i).X + 40, lstYoloRects(i).Y - 5),
FontFace.HersheyComplex, 0.3, New MCvScalar(255, 0, 0))
End If
Next
ImageBox1.Image = m
End Sub
输出结果如下图所示:
图11-2 使用YOLO进行目标检测的结果
11.5.2 SSD
SSD(Single Shot MultiBox Detector)是一种流行的目标检测算法,它使用单个神经网络同时进行对象检测和对象分类。相比于传统的目标检测算法,SSD可以快速准确地检测出图像中的对象,被广泛应用于自动驾驶、安防监控等领域。
【代码位置:frmChapter11】Button4_Click
'ssd
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
'对象分类,object_detection_classes_pascal_voc.txt文件提供了21类对象(含background)
Dim classnames() As String
classnames = File.ReadAllLines("C:\learnEmgucv\ssd\object_detection_classes_pascal_voc.txt")
'需要测试的图像文件
Dim m As New Mat("C:\learnEmgucv\dnntest.jpg", ImreadModes.Color)
Dim hm As Single = m.Height
Dim wm As Single = m.Width
Dim net As Dnn.Net
'读取SSD的推理模型文件
net = DnnInvoke.ReadNetFromCaffe("C:\learnEmgucv\ssd\MobileNetSSD_deploy.prototxt.txt",
"C:\learnEmgucv\ssd\MobileNetSSD_deploy.caffemodel")
net.SetPreferableBackend(Dnn.Backend.OpenCV)
net.SetPreferableTarget(Target.Cpu)
'输入图像必须是(300,300),参看MobileNetSSD_deploy.prototxt.txt中input_shape
Dim mCopy As New Mat
CvInvoke.Resize(m, mCopy, New Drawing.Size(300, 300))
Dim blob As Mat
blob = DnnInvoke.BlobFromImage(mCopy, 0.007843, New Size(300, 300),
New MCvScalar(127.5, 127.5, 127.5), False, False)
net.SetInput(blob)
'
Dim mout As New Mat
mout = net.Forward()
'返回四维数组
Dim fout(,,,) As Single
fout = mout.GetData()
'检测到的所有对象的数量
Dim allObjCount As Integer = fout.GetLength(2)
'识别到的对象序号
Dim lstSsdIndex As New List(Of Integer)
'置信度
Dim lstSsdConf As New List(Of Single)
'矩形
Dim lstSsdRects As New List(Of Rectangle)
For i As Integer = 0 To allObjCount - 1
'置信度
Dim conf As Single
conf = fout(0, 0, i, 2)
If conf > 0.5 Then
lstSsdConf.Add(conf)
'对应对象序号
lstSsdIndex.Add(fout(0, 0, i, 1))
'左上角X
Dim lbx As Integer = CInt(fout(0, 0, i, 3) * wm)
'左上角Y
Dim lby As Integer = CInt(fout(0, 0, i, 4) * hm)
'右下角X
Dim rtx As Integer = CInt(fout(0, 0, i, 5) * wm)
'右下角Y
Dim rty As Integer = CInt(fout(0, 0, i, 6) * hm)
'对应矩形
lstSsdRects.Add(New Rectangle(lbx, lby, rtx - lbx, rty - lby))
End If
Next
For i As Integer = 0 To lstSsdIndex.Count - 1
'检测出的对象所在矩形区域
CvInvoke.Rectangle(m, lstSsdRects(i), New MCvScalar(0, 255, 0), 1)
Dim objName As String
objName = classnames(lstSsdIndex(i))
Console.WriteLine(objName & lstSsdConf(i))
'输出检测出的对象名称
CvInvoke.PutText(m, objName,
New Point(lstSsdRects(i).X, lstSsdRects(i).Y - 5),
FontFace.HersheyTriplex, 0.3, New MCvScalar(0, 0, 255))
'输出检测出的置信度
CvInvoke.PutText(m, lstSsdConf(i),
New Point(lstSsdRects(i).X + 40, lstSsdRects(i).Y - 5),
FontFace.HersheyComplex, 0.3, New MCvScalar(255, 0, 0))
Next
ImageBox1.Image = m
End Sub
输出结果如下图所示:
图11-3使用SSD进行目标检测的结果