forked from dotnet/machinelearning-samples
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathMainWindow.xaml.vb
More file actions
181 lines (148 loc) · 7.06 KB
/
MainWindow.xaml.vb
File metadata and controls
181 lines (148 loc) · 7.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
Imports Microsoft.ML
Imports OnnxObjectDetection
Imports OpenCvSharp
Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.IO
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports Rectangle = System.Windows.Shapes.Rectangle
Partial Public Class MainWindow
Inherits System.Windows.Window
Private capture As VideoCapture
Private cameraCaptureCancellationTokenSource As CancellationTokenSource
Private outputParser As OnnxOutputParser
Private tinyYoloPredictionEngine As PredictionEngine(Of ImageInputData, TinyYoloPrediction)
Private customVisionPredictionEngine As PredictionEngine(Of ImageInputData, CustomVisionPrediction)
Private Shared ReadOnly modelsDirectory As String = Path.Combine(Environment.CurrentDirectory, "ML\OnnxModels")
Public Sub New()
InitializeComponent()
LoadModel()
End Sub
Protected Overrides Sub OnActivated(e As EventArgs)
MyBase.OnActivated(e)
StartCameraCapture()
End Sub
Protected Overrides Sub OnDeactivated(e As EventArgs)
MyBase.OnDeactivated(e)
StopCameraCapture()
End Sub
Private Sub LoadModel()
' Check for an Onnx model exported from Custom Vision
Dim customVisionExport = Directory.GetFiles(modelsDirectory, "*.zip").FirstOrDefault()
' If there is one, use it.
If customVisionExport IsNot Nothing Then
Dim customVisionModel = New CustomVisionModel(customVisionExport)
Dim modelConfigurator = New OnnxModelConfigurator(customVisionModel)
outputParser = New OnnxOutputParser(customVisionModel)
customVisionPredictionEngine = modelConfigurator.GetMlNetPredictionEngine(Of CustomVisionPrediction)()
Else ' Otherwise default to Tiny Yolo Onnx model
Dim tinyYoloModel = New TinyYoloModel(Path.Combine(modelsDirectory, "TinyYolo2_model.onnx"))
Dim modelConfigurator = New OnnxModelConfigurator(tinyYoloModel)
outputParser = New OnnxOutputParser(tinyYoloModel)
tinyYoloPredictionEngine = modelConfigurator.GetMlNetPredictionEngine(Of TinyYoloPrediction)()
End If
End Sub
Private Sub StartCameraCapture()
cameraCaptureCancellationTokenSource = New CancellationTokenSource
Task.Run(Function() CaptureCamera(cameraCaptureCancellationTokenSource.Token), cameraCaptureCancellationTokenSource.Token)
End Sub
Private Sub StopCameraCapture()
cameraCaptureCancellationTokenSource?.Cancel()
End Sub
Private Async Function CaptureCamera(token As CancellationToken) As Task
If capture Is Nothing Then
capture = New VideoCapture(CaptureDevice.DShow)
End If
capture.Open(0)
If capture.IsOpened() Then
Do While Not token.IsCancellationRequested
Using memoryStream = capture.RetrieveMat.Flip(FlipMode.Y).ToMemoryStream()
Await Dispatcher.BeginInvoke(
Sub()
Dim imageSource = New BitmapImage
imageSource.BeginInit()
imageSource.CacheOption = BitmapCacheOption.OnLoad
imageSource.StreamSource = memoryStream
imageSource.EndInit()
WebCamImage.Source = imageSource
End Sub)
Using bitmapImage As New Bitmap(memoryStream)
Await ParseWebCamFrame(bitmapImage, token)
End Using
End Using
Loop
capture.Release()
End If
End Function
Private Async Function ParseWebCamFrame(bitmap As Bitmap, token As CancellationToken) As Task
If customVisionPredictionEngine Is Nothing AndAlso tinyYoloPredictionEngine Is Nothing Then
Return
End If
Dim frame = New ImageInputData With {.Image = bitmap}
Dim filteredBoxes = DetectObjectsUsingModel(frame)
If Not token.IsCancellationRequested Then
Await Dispatcher.BeginInvoke(
Sub() DrawOverlays(filteredBoxes, WebCamImage.ActualHeight, WebCamImage.ActualWidth))
End If
End Function
Public Function DetectObjectsUsingModel(imageInputData As ImageInputData) As List(Of BoundingBox)
Dim labels = If(customVisionPredictionEngine?.Predict(imageInputData).PredictedLabels, tinyYoloPredictionEngine?.Predict(imageInputData).PredictedLabels)
Dim boundingBoxes = outputParser.ParseOutputs(labels)
Dim filteredBoxes = outputParser.FilterBoundingBoxes(boundingBoxes, 5, 0.5F)
Return filteredBoxes
End Function
Private Sub DrawOverlays(filteredBoxes As List(Of BoundingBox), originalHeight As Double, originalWidth As Double)
WebCamCanvas.Children.Clear()
For Each box In filteredBoxes
' process output boxes
Dim x As Double = Math.Max(box.Dimensions.X, 0)
Dim y As Double = Math.Max(box.Dimensions.Y, 0)
Dim width As Double = Math.Min(originalWidth - x, box.Dimensions.Width)
Dim height As Double = Math.Min(originalHeight - y, box.Dimensions.Height)
' fit to current image size
x = originalWidth * x / ImageSettings.imageWidth
y = originalHeight * y / ImageSettings.imageHeight
width = originalWidth * width / ImageSettings.imageWidth
height = originalHeight * height / ImageSettings.imageHeight
Dim boxColor = box.BoxColor.ToMediaColor()
Dim objBox = New Rectangle With {
.Width = width,
.Height = height,
.Fill = New SolidColorBrush(Colors.Transparent),
.Stroke = New SolidColorBrush(boxColor),
.StrokeThickness = 2.0,
.Margin = New Thickness(x, y, 0, 0)
}
Dim objDescription = New TextBlock With {
.Margin = New Thickness(x + 4, y + 4, 0, 0),
.Text = box.Description,
.FontWeight = FontWeights.Bold,
.Width = 126,
.Height = 21,
.TextAlignment = TextAlignment.Center
}
Dim objDescriptionBackground = New Rectangle With {
.Width = 134,
.Height = 29,
.Fill = New SolidColorBrush(boxColor),
.Margin = New Thickness(x, y, 0, 0)
}
WebCamCanvas.Children.Add(objDescriptionBackground)
WebCamCanvas.Children.Add(objDescription)
WebCamCanvas.Children.Add(objBox)
Next box
End Sub
End Class
Friend Module ColorExtensions
<System.Runtime.CompilerServices.Extension>
Friend Function ToMediaColor(drawingColor As System.Drawing.Color) As System.Windows.Media.Color
Return System.Windows.Media.Color.FromArgb(drawingColor.A, drawingColor.R, drawingColor.G, drawingColor.B)
End Function
End Module