PB Unity commited on
Commit
70c3ec2
1 Parent(s): 14c8207

Upload 4 files

Browse files
.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
+ hand_landmark.sentis filter=lfs diff=lfs merge=lfs -text
RunHandLandmark.cs ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ using UnityEngine;
2
+ using Unity.Sentis;
3
+ using UnityEngine.Video;
4
+ using UnityEngine.UI;
5
+ using Lays = Unity.Sentis.Layers;
6
+ using System.Collections.Generic;
7
+
8
+ /*
9
+ * Hand Landmarks Inference
10
+ * ========================
11
+ *
12
+ * Basic inference script for blaze hand landmarks
13
+ *
14
+ * Put this script on the Main Camera
15
+ * Put hand_landmark.sentis in the Assets/StreamingAssets folder
16
+ * Create a RawImage of in the scene
17
+ * Put a link to that image in previewUI
18
+ * Put a video in Assets/StreamingAssets folder and put the name of it int videoName
19
+ * Or put a test image in inputImage
20
+ * Set inputType to appropriate input
21
+ */
22
+
23
+
24
+ public class RunHandLandmark : MonoBehaviour
25
+ {
26
+ //Drag a link to a raw image here:
27
+ public RawImage previewUI = null;
28
+
29
+ // Put your bounding box sprite image here
30
+ public Sprite faceTexture;
31
+
32
+ // 6 optional sprite images (left eye, right eye, nose, mouth, left ear, right ear)
33
+ public Sprite[] markerTextures;
34
+
35
+ public string videoName = "chatting.mp4";
36
+
37
+ public Texture2D inputImage;
38
+
39
+ public InputType inputType = InputType.Video;
40
+
41
+ //Resolution of preview image or video
42
+ Vector2Int resolution = new Vector2Int(640, 640);
43
+ WebCamTexture webcam;
44
+ VideoPlayer video;
45
+
46
+ const BackendType backend = BackendType.GPUCompute;
47
+
48
+ RenderTexture targetTexture;
49
+ public enum InputType { Image, Video, Webcam };
50
+
51
+ IWorker worker;
52
+
53
+ //Holds image size
54
+ const int size = 224;
55
+
56
+ Ops ops;
57
+ ITensorAllocator allocator;
58
+
59
+ Model model;
60
+
61
+ //webcam device name:
62
+ const string deviceName = "";
63
+
64
+ bool closing = false;
65
+
66
+ public struct BoundingBox
67
+ {
68
+ public float centerX;
69
+ public float centerY;
70
+ public float width;
71
+ public float height;
72
+ }
73
+
74
+ List<GameObject> boxPool = new();
75
+ void Start()
76
+ {
77
+ allocator = new TensorCachingAllocator();
78
+
79
+ //(Note: if using a webcam on mobile get permissions here first)
80
+
81
+ targetTexture = new RenderTexture(resolution.x, resolution.y, 0);
82
+ previewUI.texture = targetTexture;
83
+
84
+ SetupInput();
85
+ SetupModel();
86
+ SetupEngine();
87
+ }
88
+
89
+ void SetupModel()
90
+ {
91
+ model = ModelLoader.Load(Application.streamingAssetsPath + "/hand_landmark.sentis");
92
+ }
93
+ public void SetupEngine()
94
+ {
95
+ worker = WorkerFactory.CreateWorker(backend, model);
96
+ ops = WorkerFactory.CreateOps(backend, allocator);
97
+ }
98
+
99
+ void SetupInput()
100
+ {
101
+ switch (inputType)
102
+ {
103
+ case InputType.Webcam:
104
+ {
105
+ webcam = new WebCamTexture(deviceName, resolution.x, resolution.y);
106
+ webcam.requestedFPS = 30;
107
+ webcam.Play();
108
+ break;
109
+ }
110
+ case InputType.Video:
111
+ {
112
+ video = gameObject.AddComponent<VideoPlayer>();//new VideoPlayer();
113
+ video.renderMode = VideoRenderMode.APIOnly;
114
+ video.source = VideoSource.Url;
115
+ video.url = Application.streamingAssetsPath + "/"+videoName;
116
+ video.isLooping = true;
117
+ video.Play();
118
+ break;
119
+ }
120
+ default:
121
+ {
122
+ Graphics.Blit(inputImage, targetTexture);
123
+ }
124
+ break;
125
+ }
126
+ }
127
+
128
+ void Update()
129
+ {
130
+ if (inputType == InputType.Webcam)
131
+ {
132
+ // Format video input
133
+ if (!webcam.didUpdateThisFrame) return;
134
+
135
+ var aspect1 = (float)webcam.width / webcam.height;
136
+ var aspect2 = (float)resolution.x / resolution.y;
137
+ var gap = aspect2 / aspect1;
138
+
139
+ var vflip = webcam.videoVerticallyMirrored;
140
+ var scale = new Vector2(gap, vflip ? -1 : 1);
141
+ var offset = new Vector2((1 - gap) / 2, vflip ? 1 : 0);
142
+
143
+ Graphics.Blit(webcam, targetTexture, scale, offset);
144
+ }
145
+ if (inputType == InputType.Video)
146
+ {
147
+ var aspect1 = (float)video.width / video.height;
148
+ var aspect2 = (float)resolution.x / resolution.y;
149
+ var gap = aspect2 / aspect1;
150
+
151
+ var vflip = false;
152
+ var scale = new Vector2(gap, vflip ? -1 : 1);
153
+ var offset = new Vector2((1 - gap) / 2, vflip ? 1 : 0);
154
+ Graphics.Blit(video.texture, targetTexture, scale, offset);
155
+ }
156
+ if (inputType == InputType.Image)
157
+ {
158
+ Graphics.Blit(inputImage, targetTexture);
159
+ }
160
+
161
+ if (Input.GetKeyDown(KeyCode.Escape))
162
+ {
163
+ closing = true;
164
+ Application.Quit();
165
+ }
166
+
167
+ if (Input.GetKeyDown(KeyCode.P))
168
+ {
169
+ previewUI.enabled = !previewUI.enabled;
170
+ }
171
+ }
172
+
173
+ void LateUpdate()
174
+ {
175
+ if (!closing)
176
+ {
177
+ RunInference(targetTexture);
178
+ }
179
+ }
180
+
181
+ void DrawLandmarks(TensorFloat landmarks, Vector2 scale)
182
+ {
183
+ //Draw the landmarks on the hand
184
+ for (int j = 0; j < 21; j++)
185
+ {
186
+ var marker = new BoundingBox
187
+ {
188
+ centerX = landmarks[0, j * 3] * scale.x - (size / 2) * scale.x,
189
+ centerY = landmarks[0, j * 3 + 1] * scale.y - (size/2) * scale.y,
190
+ width = 8f * scale.x,
191
+ height = 8f * scale.y,
192
+ };
193
+ DrawBox(marker, j < markerTextures.Length ? markerTextures[j] : faceTexture, j);
194
+ }
195
+ }
196
+
197
+ void RunInference(Texture source)
198
+ {
199
+ var transform = new TextureTransform();
200
+ transform.SetDimensions(size, size, 3);
201
+ transform.SetTensorLayout(0, 1, 2, 3);
202
+ using var image0 = TextureConverter.ToTensor(source, transform);
203
+
204
+ // Pre-process the image to make input in range (-1..1)
205
+ using var image = ops.Mad(image0, 2f, -1f);
206
+
207
+ worker.Execute(image);
208
+
209
+ using var landmarks = worker.PeekOutput("Identity") as TensorFloat;
210
+
211
+ ClearAnnotations();
212
+
213
+ Vector2 markerScale = previewUI.rectTransform.rect.size/ size;
214
+ landmarks.MakeReadable();
215
+ DrawLandmarks(landmarks, markerScale);
216
+
217
+ bool showExtraInformation = false;
218
+ if (showExtraInformation)
219
+ {
220
+ using var A = worker.PeekOutput("Identity_1") as TensorFloat;
221
+ using var B = worker.PeekOutput("Identity_2") as TensorFloat;
222
+ A.MakeReadable();
223
+ B.MakeReadable();
224
+ Debug.Log("A,B=" + A[0, 0] + "," + B[0, 0]);
225
+ }
226
+ }
227
+
228
+ public void DrawBox(BoundingBox box, Sprite sprite, int ID)
229
+ {
230
+ GameObject panel = null;
231
+ if (ID >= boxPool.Count)
232
+ {
233
+ panel = new GameObject("landmark");
234
+ panel.AddComponent<CanvasRenderer>();
235
+ panel.AddComponent<Image>();
236
+ panel.transform.SetParent(previewUI.transform, false);
237
+ boxPool.Add(panel);
238
+ }
239
+ else
240
+ {
241
+ panel = boxPool[ID];
242
+ panel.SetActive(true);
243
+ }
244
+
245
+ var img = panel.GetComponent<Image>();
246
+ img.color = Color.white;
247
+ img.sprite = sprite;
248
+ img.type = Image.Type.Sliced;
249
+
250
+ panel.transform.localPosition = new Vector3(box.centerX, -box.centerY);
251
+ RectTransform rt = panel.GetComponent<RectTransform>();
252
+ rt.sizeDelta = new Vector2(box.width, box.height);
253
+ }
254
+
255
+ public void ClearAnnotations()
256
+ {
257
+ for (int i = 0; i < boxPool.Count; i++)
258
+ {
259
+ boxPool[i].SetActive(false);
260
+ }
261
+ }
262
+
263
+ void CleanUp()
264
+ {
265
+ closing = true;
266
+ ops?.Dispose();
267
+ allocator?.Dispose();
268
+ if (webcam) Destroy(webcam);
269
+ if (video) Destroy(video);
270
+ RenderTexture.active = null;
271
+ targetTexture.Release();
272
+ worker?.Dispose();
273
+ worker = null;
274
+ }
275
+
276
+ void OnDestroy()
277
+ {
278
+ CleanUp();
279
+ }
280
+
281
+ }
282
+
hand_landmark.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:caeea4465a5b7bf68081d9ba6ce195dcb6dcbaadbe83c339a4f2860e9db7eec2
3
+ size 3852998
hand_landmark.sentis ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:584d24cd0814e354d9f14b74a53a921c5ff0c31ca282872cc0ca3b6dc21119de
3
+ size 3879993
hand_tracking_preview.png ADDED