Paul Bird commited on
Commit
7130ecc
1 Parent(s): a6377c7

Upload 4 files

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -0
  2. RunYOLO8n.cs +270 -0
  3. classes.txt +80 -0
  4. yolov8n.onnx +3 -0
  5. yolov8n.sentis +3 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ yolov8n.sentis filter=lfs diff=lfs merge=lfs -text
RunYOLO8n.cs ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ using System.Collections.Generic;
2
+ using Unity.Sentis;
3
+ using UnityEngine;
4
+ using UnityEngine.UI;
5
+ using UnityEngine.Video;
6
+ using Lays = Unity.Sentis.Layers;
7
+
8
+ /*
9
+ * YOLOv8n Inference Script
10
+ * ========================
11
+ *
12
+ * Place this script on the Main Camera.
13
+ *
14
+ * Place the yolov8n.sentis file and a *.mp4 video file in the Assets/StreamingAssets folder
15
+ * Create a RawImage in your scene and set it as the displayImage field
16
+ * Drag the classes.txt into the labelsAsset field
17
+ * Add a reference to a sprite image for the bounding box and a font for the text
18
+ *
19
+ */
20
+
21
+
22
+ public class RunYOLO8n : MonoBehaviour
23
+ {
24
+ const string modelName = "yolov8n.sentis";
25
+ // Change this to the name of the video you put in StreamingAssets folder:
26
+ const string videoName = "giraffes.mp4";
27
+ // Link the classes.txt here:
28
+ public TextAsset labelsAsset;
29
+ // Create a Raw Image in the scene and link it here:
30
+ public RawImage displayImage;
31
+ // Link to a bounding box texture here:
32
+ public Sprite boxTexture;
33
+ // Link to the font for the labels:
34
+ public Font font;
35
+
36
+ const BackendType backend = BackendType.GPUCompute;
37
+
38
+ private Transform displayLocation;
39
+ private Model model;
40
+ private IWorker engine;
41
+ private string[] labels;
42
+ private RenderTexture targetRT;
43
+
44
+
45
+ //Image size for the model
46
+ private const int imageWidth = 640;
47
+ private const int imageHeight = 640;
48
+
49
+ //The number of classes in the model
50
+ private const int numClasses = 80;
51
+
52
+ private VideoPlayer video;
53
+
54
+ List<GameObject> boxPool = new List<GameObject>();
55
+
56
+ [SerializeField, Range(0, 1)] float iouThreshold = 0.5f;
57
+ [SerializeField, Range(0, 1)] float scoreThreshold = 0.5f;
58
+ int maxOutputBoxes = 64;
59
+
60
+ //For using tensor operators:
61
+ Ops ops;
62
+
63
+ //bounding box data
64
+ public struct BoundingBox
65
+ {
66
+ public float centerX;
67
+ public float centerY;
68
+ public float width;
69
+ public float height;
70
+ public string label;
71
+ }
72
+
73
+
74
+ void Start()
75
+ {
76
+ Application.targetFrameRate = 60;
77
+ Screen.orientation = ScreenOrientation.LandscapeLeft;
78
+
79
+ ops = WorkerFactory.CreateOps(backend, null);
80
+
81
+ //Parse neural net labels
82
+ labels = labelsAsset.text.Split('\n');
83
+
84
+ LoadModel();
85
+
86
+ targetRT = new RenderTexture(imageWidth, imageHeight, 0);
87
+
88
+ //Create image to display video
89
+ displayLocation = displayImage.transform;
90
+
91
+ //Create engine to run model
92
+ engine = WorkerFactory.CreateWorker(backend, model);
93
+
94
+ SetupInput();
95
+ }
96
+
97
+ void LoadModel()
98
+ {
99
+ //Load model
100
+ model = ModelLoader.Load(Application.streamingAssetsPath + "/" + modelName);
101
+
102
+ //The classes are also stored here in JSON format:
103
+ Debug.Log($"Class names: \n{model.Metadata["names"]}");
104
+
105
+ //We need to add some layers to choose the best boxes with the NMSLayer
106
+
107
+ //Set constants
108
+ model.AddConstant(new Lays.Constant("0", new int[] { 0 }));
109
+ model.AddConstant(new Lays.Constant("1", new int[] { 1 }));
110
+ model.AddConstant(new Lays.Constant("4", new int[] { 4 }));
111
+ model.AddConstant(new Lays.Constant("classes_plus_4", new int[] { numClasses + 4 }));
112
+ model.AddConstant(new Lays.Constant("maxOutputBoxes", new int[] { maxOutputBoxes }));
113
+ model.AddConstant(new Lays.Constant("iouThreshold", new float[] { iouThreshold }));
114
+ model.AddConstant(new Lays.Constant("scoreThreshold", new float[] { scoreThreshold }));
115
+
116
+ //Add layers
117
+ model.AddLayer(new Lays.Slice("boxCoords0", "output0", "0", "4", "1"));
118
+ model.AddLayer(new Lays.Transpose("boxCoords", "boxCoords0", new int[] { 0, 2, 1 }));
119
+ model.AddLayer(new Lays.Slice("scores0", "output0", "4", "classes_plus_4", "1"));
120
+
121
+ model.AddLayer(new Lays.NonMaxSuppression("NMS", "boxCoords", "scores0",
122
+ "maxOutputBoxes", "iouThreshold", "scoreThreshold",
123
+ centerPointBox: Lays.CenterPointBox.Corners
124
+ ));
125
+
126
+ model.outputs.Clear();
127
+ model.AddOutput("boxCoords");
128
+ model.AddOutput("NMS");
129
+ }
130
+
131
+ void SetupInput()
132
+ {
133
+ video = gameObject.AddComponent<VideoPlayer>();
134
+ video.renderMode = VideoRenderMode.APIOnly;
135
+ video.source = VideoSource.Url;
136
+ video.url = Application.streamingAssetsPath + "/" + videoName;
137
+ video.isLooping = true;
138
+ video.Play();
139
+ }
140
+
141
+ private void Update()
142
+ {
143
+ ExecuteML();
144
+
145
+ if (Input.GetKeyDown(KeyCode.Escape))
146
+ {
147
+ Application.Quit();
148
+ }
149
+ }
150
+
151
+ public void ExecuteML()
152
+ {
153
+ ClearAnnotations();
154
+
155
+ if (video && video.texture)
156
+ {
157
+ float aspect = video.width * 1f / video.height;
158
+ Graphics.Blit(video.texture, targetRT, new Vector2(1f / aspect, 1), new Vector2(0, 0));
159
+ displayImage.texture = targetRT;
160
+ }
161
+ else return;
162
+
163
+ using var input = TextureConverter.ToTensor(targetRT, imageWidth, imageHeight, 3);
164
+ engine.Execute(input);
165
+
166
+ var boxCoords = engine.PeekOutput("boxCoords") as TensorFloat;
167
+ var NMS = engine.PeekOutput("NMS") as TensorInt;
168
+
169
+ using var boxIDs = ops.Slice(NMS, new int[] { 2 }, new int[] { 3 }, new int[] { 1 }, new int[] { 1 });
170
+ using var boxIDsFlat = boxIDs.ShallowReshape(new TensorShape(boxIDs.shape.length)) as TensorInt;
171
+ using var output = ops.Gather(boxCoords, boxIDsFlat, 1);
172
+
173
+ output.MakeReadable();
174
+ NMS.MakeReadable();
175
+
176
+ float displayWidth = displayImage.rectTransform.rect.width;
177
+ float displayHeight = displayImage.rectTransform.rect.height;
178
+
179
+ float scaleX = displayWidth / imageWidth;
180
+ float scaleY = displayHeight / imageHeight;
181
+
182
+ //Draw the bounding boxes
183
+ for (int n = 0; n < output.shape[1]; n++)
184
+ {
185
+ var box = new BoundingBox
186
+ {
187
+ centerX = output[0, n, 0] * scaleX - displayWidth / 2,
188
+ centerY = output[0, n, 1] * scaleY - displayHeight / 2,
189
+ width = output[0, n, 2] * scaleX,
190
+ height = output[0, n, 3] * scaleY,
191
+ label = labels[(int)NMS[n, 1]]
192
+ };
193
+ DrawBox(box, n);
194
+ }
195
+ }
196
+
197
+ public void DrawBox(BoundingBox box , int id)
198
+ {
199
+ //Create the bounding box graphic or get from pool
200
+ GameObject panel;
201
+ if (id < boxPool.Count)
202
+ {
203
+ panel = boxPool[id];
204
+ panel.SetActive(true);
205
+ }
206
+ else
207
+ {
208
+ panel = CreateNewBox(Color.yellow);
209
+ }
210
+ //Set box position
211
+ panel.transform.localPosition = new Vector3(box.centerX, -box.centerY);
212
+
213
+ //Set box size
214
+ RectTransform rt = panel.GetComponent<RectTransform>();
215
+ rt.sizeDelta = new Vector2(box.width, box.height);
216
+
217
+ //Set label text
218
+ var label = panel.GetComponentInChildren<Text>();
219
+ label.text = box.label;
220
+ }
221
+
222
+ public GameObject CreateNewBox(Color color)
223
+ {
224
+ //Create the box and set image
225
+
226
+ var panel = new GameObject("ObjectBox");
227
+ panel.AddComponent<CanvasRenderer>();
228
+ Image img = panel.AddComponent<Image>();
229
+ img.color = color;
230
+ img.sprite = boxTexture;
231
+ img.type = Image.Type.Sliced;
232
+ panel.transform.SetParent(displayLocation, false);
233
+
234
+ //Create the label
235
+
236
+ var text = new GameObject("ObjectLabel");
237
+ text.AddComponent<CanvasRenderer>();
238
+ text.transform.SetParent(panel.transform, false);
239
+ Text txt = text.AddComponent<Text>();
240
+ txt.font = font;
241
+ txt.color = color;
242
+ txt.fontSize = 40;
243
+ txt.horizontalOverflow = HorizontalWrapMode.Overflow;
244
+
245
+ RectTransform rt2 = text.GetComponent<RectTransform>();
246
+ rt2.offsetMin = new Vector2(20, rt2.offsetMin.y);
247
+ rt2.offsetMax = new Vector2(0, rt2.offsetMax.y);
248
+ rt2.offsetMin = new Vector2(rt2.offsetMin.x, 0);
249
+ rt2.offsetMax = new Vector2(rt2.offsetMax.x, 30);
250
+ rt2.anchorMin = new Vector2(0, 0);
251
+ rt2.anchorMax = new Vector2(1, 1);
252
+
253
+ boxPool.Add(panel);
254
+ return panel;
255
+ }
256
+
257
+ public void ClearAnnotations()
258
+ {
259
+ foreach(var box in boxPool)
260
+ {
261
+ box.SetActive(false);
262
+ }
263
+ }
264
+
265
+ private void OnDestroy()
266
+ {
267
+ engine?.Dispose();
268
+ ops?.Dispose();
269
+ }
270
+ }
classes.txt ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ person
2
+ bicycle
3
+ car
4
+ motorbike
5
+ aeroplane
6
+ bus
7
+ train
8
+ truck
9
+ boat
10
+ traffic light
11
+ fire hydrant
12
+ stop sign
13
+ parking meter
14
+ bench
15
+ bird
16
+ cat
17
+ dog
18
+ horse
19
+ sheep
20
+ cow
21
+ elephant
22
+ bear
23
+ zebra
24
+ giraffe
25
+ backpack
26
+ umbrella
27
+ handbag
28
+ tie
29
+ suitcase
30
+ frisbee
31
+ skis
32
+ snowboard
33
+ sports ball
34
+ kite
35
+ baseball bat
36
+ baseball glove
37
+ skateboard
38
+ surfboard
39
+ tennis racket
40
+ bottle
41
+ wine glass
42
+ cup
43
+ fork
44
+ knife
45
+ spoon
46
+ bowl
47
+ banana
48
+ apple
49
+ sandwich
50
+ orange
51
+ broccoli
52
+ carrot
53
+ hot dog
54
+ pizza
55
+ donut
56
+ cake
57
+ chair
58
+ sofa
59
+ potted plant
60
+ bed
61
+ dining table
62
+ toilet
63
+ tv monitor
64
+ laptop
65
+ mouse
66
+ remote
67
+ keyboard
68
+ cell phone
69
+ microwave
70
+ oven
71
+ toaster
72
+ sink
73
+ refrigerator
74
+ book
75
+ clock
76
+ vase
77
+ scissors
78
+ teddy bear
79
+ hair drier
80
+ toothbrush
yolov8n.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:00113c3ec2b9fd39142b2adb82c0f67d694eb2856413e14b37602d77eddfea08
3
+ size 6434150
yolov8n.sentis ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2a788b23743661e23da08e893fb7efb507e912a017bfe98604b36a9609f9ffb3
3
+ size 12897918