wzf19947 commited on
Commit
e20aaaa
·
1 Parent(s): 07b75e0

first commit

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ 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
+ *.jpg filter=lfs diff=lfs merge=lfs -text
37
+ *.axmodel filter=lfs diff=lfs merge=lfs -text
38
+ *.png filter=lfs diff=lfs merge=lfs -text
AX650/fall_ax650_npu3.axmodel ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0ee38051240bd19e4a9b77030e983378ced8ac581f9f7c824349527340613eb8
3
+ size 1129098
README.md ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: agpl-3.0
3
+ language:
4
+ - en
5
+ pipeline_tag: object-detection
6
+ tags:
7
+ - Axera
8
+ - YOLOv7-pose
9
+ - NPU
10
+ - Object Detection
11
+ - Keypoint Detection
12
+ ---
13
+
14
+ # fall-axera
15
+
16
+ This version of **fall-axera** has been converted to run on the Axera NPU using **w8a16** quantization. It is trained with modified yolov7-pose model to detect bbox and 14 keypoints of human, and to determine whether a fall behavior is likely to occur.
17
+
18
+ ## Supported Classes
19
+
20
+ This model is trained to detect the following classes:
21
+ 1. **normal**
22
+ 2. **fall**
23
+
24
+ ## Supported keypoints
25
+ This model is trained to detect the following 14 keypoints:
26
+ ```
27
+ "keypoints": { 0: "right shoulder", 1: "right elbow", 2: "right wrist", 3: "left shoulder", 4: "left elbow", 5: "left wrist", 6: "right hip", 7: "right knee", 8: "right ankle", 9: "left hip", 10: "left knee", 11: "left ankle", 12: "head tops", 13: "upper neck" }"
28
+ ```
29
+
30
+ Compatible with Pulsar2 version: 5.2.
31
+
32
+ ## Convert tools links:
33
+
34
+ For those who are interested in model conversion, you can try to export axmodel through:
35
+ - [The repo of AXera Platform](https://github.com/AXERA-TECH/ax-samples), where you can get the detailed guide.
36
+ - [Pulsar2 Link, How to Convert ONNX to axmodel](https://pulsar2-docs.readthedocs.io/en/latest/pulsar2/introduction.html)
37
+
38
+ ## Support Platform
39
+
40
+ https://docs.m5stack.com/zh_CN/ai_hardware/AI_Pyramid-Pro
41
+
42
+ - **AX650N/AX8850**
43
+ - [M4N-Dock(爱芯派Pro)](https://wiki.sipeed.com/hardware/zh/maixIV/m4ndock/m4ndock.html)
44
+ - [AI Pyramid](https://docs.m5stack.com/zh_CN/ai_hardware/AI_Pyramid-Pro)
45
+ - [M.2 Accelerator card](https://docs.m5stack.com/en/ai_hardware/LLM-8850_Card)
46
+
47
+ ## How to use
48
+
49
+ Download all files from this repository to the device.
50
+
51
+ ### python env requirement
52
+
53
+ #### pyaxengine
54
+
55
+ https://github.com/AXERA-TECH/pyaxengine
56
+
57
+ ```bash
58
+ wget https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3.rc2/axengine-0.1.3-py3-none-any.whl
59
+ pip install axengine-0.1.3-py3-none-any.whl
60
+ ```
61
+
62
+ ### Inference with AX650 Host, such as M4N-Dock(爱芯派Pro)
63
+
64
+ Input image:
65
+ ![](fall4.png)
66
+
67
+ run
68
+ ```
69
+ python3 axmodel_infer_fall.py
70
+ ```
71
+
72
+ ```
73
+ root@ax650:~/fall-axera# python3 axmodel_infer_fall.py
74
+ [INFO] Available providers: ['AxEngineExecutionProvider', 'AXCLRTExecutionProvider']
75
+ [INFO] Using provider: AxEngineExecutionProvider
76
+ [INFO] Chip type: ChipType.MC50
77
+ [INFO] VNPU type: VNPUType.DISABLED
78
+ [INFO] Engine version: 2.12.0s
79
+ [INFO] Model type: 2 (triple core)
80
+ [INFO] Compiler version: 5.2 eccb31f5
81
+ class: fall left:281 top:396 right:734 bottom:629 conf: 74%
82
+ Result saved to axmodel_res.jpg
83
+
84
+ ```
85
+
86
+ Output image:
87
+ ![](axmodel_res.jpg)
88
+
89
+ ### Extra
90
+ This example only shows the model's predicted bounding boxes and keypoints. You can further assist in determining human falls based on the physical information of the boxes and keypoints, or by adding tracking and action recognition models like st-gcn. From the experiments I have conducted, factors such as occlusion, direction of falling, camera angle, and even the scene (such as on the bed or on the floor) can affect the results of fall detection.
91
+
axmodel_infer_fall.py ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import axengine as axe
4
+ import matplotlib
5
+ import argparse
6
+
7
+ class Colors:
8
+
9
+ def __init__(self):
10
+ self.palette = [self.hex2rgb(c) for c in matplotlib.colors.TABLEAU_COLORS.values()]
11
+ self.n = len(self.palette)
12
+
13
+ def __call__(self, i, bgr=False):
14
+ c = self.palette[int(i) % self.n]
15
+ return (c[2], c[1], c[0]) if bgr else c
16
+
17
+ @staticmethod
18
+ def hex2rgb(h):
19
+ return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
20
+
21
+ colors = Colors()
22
+
23
+ def plot_one_box(x, im, color=None, label=None, line_thickness=3, kpt_label=False, kpts=None, steps=2, orig_shape=None):
24
+
25
+ assert im.data.contiguous, 'Image not contiguous. Apply np.ascontiguousarray(im) to plot_on_box() input image.'
26
+ tl = line_thickness or round(0.002 * (im.shape[0] + im.shape[1]) / 2) + 1
27
+
28
+ c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
29
+ cv2.rectangle(im, c1, c2, color, thickness=tl*1//3, lineType=cv2.LINE_AA)
30
+
31
+ if label:
32
+ if len(label.split(' ')) > 1:
33
+
34
+ tf = max(tl - 1, 1)
35
+ t_size = cv2.getTextSize(label, 0, fontScale=tl / 6, thickness=tf)[0]
36
+ c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
37
+ cv2.rectangle(im, c1, c2, color, -1, cv2.LINE_AA)
38
+ cv2.putText(im, label, (c1[0], c1[1] - 2), 0, tl / 6, [225, 255, 255], thickness=tf//2, lineType=cv2.LINE_AA)
39
+ if kpt_label:
40
+ plot_skeleton_kpts(im, kpts, steps, orig_shape=orig_shape)
41
+
42
+
43
+
44
+ def plot_skeleton_kpts(im, kpts, steps, orig_shape=None):
45
+
46
+ palette = np.array([[255, 128, 0], [255, 153, 51], [255, 178, 102],
47
+ [230, 230, 0], [255, 153, 255], [153, 204, 255],
48
+ [255, 102, 255], [255, 51, 255], [102, 178, 255],
49
+ [51, 153, 255], [255, 153, 153], [255, 102, 102],
50
+ [255, 51, 51], [153, 255, 153], [102, 255, 102],
51
+ [51, 255, 51], [0, 255, 0], [0, 0, 255], [255, 0, 0],
52
+ [255, 255, 255]])
53
+ num_kpts = len(kpts) // steps
54
+
55
+ skeleton = [[1, 2], [2, 3], [14, 1], [14, 4], [4, 5], [5, 6], [13, 14], [7, 14], [10, 14], [7, 8], [8, 9],[10,11],[11, 12]]
56
+
57
+ pose_limb_color = palette[[9, 9, 9, 9, 7, 7, 7, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16][:(num_kpts+2)]]
58
+
59
+ pose_kpt_color = palette[[16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9][:num_kpts]]
60
+ radius = 5
61
+ for kid in range(num_kpts):
62
+ r, g, b = pose_kpt_color[kid]
63
+
64
+ x_coord, y_coord = kpts[steps * kid], kpts[steps * kid + 1]
65
+ if not (x_coord % 640 == 0 or y_coord % 640 == 0):
66
+ if steps == 3:
67
+ conf = kpts[steps * kid + 2]
68
+
69
+ cv2.circle(im, (int(x_coord), int(y_coord)), radius, (int(r), int(g), int(b)), -1)
70
+ cv2.putText(im,str(kid),(int(x_coord-2), int(y_coord-2)),cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0,0,255),1)
71
+
72
+ for sk_id, sk in enumerate(skeleton):
73
+ r, g, b = pose_limb_color[sk_id]
74
+
75
+ pos1 = (int(kpts[(sk[0]-1)*steps]), int(kpts[(sk[0]-1)*steps+1]))
76
+ pos2 = (int(kpts[(sk[1]-1)*steps]), int(kpts[(sk[1]-1)*steps+1]))
77
+ if steps == 3:
78
+ conf1 = kpts[(sk[0]-1)*steps+2]
79
+ conf2 = kpts[(sk[1]-1)*steps+2]
80
+
81
+ if pos1[0]%640 == 0 or pos1[1]%640==0 or pos1[0]<0 or pos1[1]<0:
82
+ continue
83
+ if pos2[0] % 640 == 0 or pos2[1] % 640 == 0 or pos2[0]<0 or pos2[1]<0:
84
+ continue
85
+ cv2.line(im, pos1, pos2, (int(r), int(g), int(b)), thickness=2)
86
+
87
+ def box_iou(box1, box2, eps=1e-7):
88
+ (a1, a2), (b1, b2) = box1.unsqueeze(1).chunk(2, 2), box2.unsqueeze(0).chunk(2, 2)
89
+ inter = (np.min(a2, b2) - np.max(a1, b1)).clamp(0).prod(2)
90
+ return inter / ((a2 - a1).prod(2) + (b2 - b1).prod(2) - inter + eps)
91
+
92
+ def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True, stride=32):
93
+
94
+ shape = im.shape[:2]
95
+ if isinstance(new_shape, int):
96
+ new_shape = (new_shape, new_shape)
97
+
98
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
99
+ if not scaleup:
100
+ r = min(r, 1.0)
101
+
102
+ ratio = r, r
103
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
104
+ dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]
105
+ if auto:
106
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride)
107
+ elif scaleFill:
108
+ dw, dh = 0.0, 0.0
109
+ new_unpad = (new_shape[1], new_shape[0])
110
+ ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]
111
+
112
+ dw /= 2
113
+ dh /= 2
114
+
115
+ if shape[::-1] != new_unpad:
116
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
117
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
118
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
119
+ im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
120
+ return im, ratio, (dw, dh)
121
+
122
+ def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None, kpt_label=False, step=2):
123
+
124
+ if ratio_pad is None:
125
+ gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])
126
+ pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2
127
+ else:
128
+ gain = ratio_pad[0]
129
+ pad = ratio_pad[1]
130
+ if isinstance(gain, (list, tuple)):
131
+ gain = gain[0]
132
+ if not kpt_label:
133
+ coords[:, [0, 2]] -= pad[0]
134
+ coords[:, [1, 3]] -= pad[1]
135
+ coords[:, [0, 2]] /= gain
136
+ coords[:, [1, 3]] /= gain
137
+ else:
138
+ coords[:, 0::step] -= pad[0]
139
+ coords[:, 1::step] -= pad[1]
140
+ coords[:, 0::step] /= gain
141
+ coords[:, 1::step] /= gain
142
+
143
+ return coords
144
+
145
+
146
+ def clip_coords(boxes, img_shape, step=2):
147
+
148
+ boxes[:, 0::step].clamp_(0, img_shape[1])
149
+ boxes[:, 1::step].clamp_(0, img_shape[0])
150
+
151
+ def model_inference(model_path=None, input=None):
152
+ session = axe.InferenceSession(model_path, None)
153
+ input_name = session.get_inputs()[0].name
154
+ output = session.run(None, {input_name: input})
155
+ return output
156
+
157
+ def xywh2xyxy(x):
158
+
159
+ y = np.copy(x)
160
+ y[..., 0] = x[..., 0] - x[..., 2] / 2
161
+ y[..., 1] = x[..., 1] - x[..., 3] / 2
162
+ y[..., 2] = x[..., 0] + x[..., 2] / 2
163
+ y[..., 3] = x[..., 1] + x[..., 3] / 2
164
+ return y
165
+
166
+ def nms_boxes(boxes, scores):
167
+
168
+ x = boxes[:, 0]
169
+ y = boxes[:, 1]
170
+ w = boxes[:, 2] - boxes[:, 0]
171
+ h = boxes[:, 3] - boxes[:, 1]
172
+
173
+ areas = w * h
174
+ order = scores.argsort()[::-1]
175
+
176
+ keep = []
177
+ while order.size > 0:
178
+ i = order[0]
179
+ keep.append(i)
180
+
181
+ xx1 = np.maximum(x[i], x[order[1:]])
182
+ yy1 = np.maximum(y[i], y[order[1:]])
183
+ xx2 = np.minimum(x[i] + w[i], x[order[1:]] + w[order[1:]])
184
+ yy2 = np.minimum(y[i] + h[i], y[order[1:]] + h[order[1:]])
185
+
186
+ w1 = np.maximum(0.0, xx2 - xx1 + 0.00001)
187
+ h1 = np.maximum(0.0, yy2 - yy1 + 0.00001)
188
+ inter = w1 * h1
189
+
190
+ ovr = inter / (areas[i] + areas[order[1:]] - inter)
191
+ inds = np.where(ovr <= 0.45)[0]
192
+
193
+ order = order[inds + 1]
194
+ keep = np.array(keep)
195
+ return keep
196
+
197
+ def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False,
198
+ labels=(), kpt_label=False, nc=None, nkpt=14):
199
+
200
+ if nc is None:
201
+ nc = prediction.shape[2] - 5 if not kpt_label else prediction.shape[2] - (5+3*nkpt)
202
+ xc = prediction[..., 4] > conf_thres
203
+
204
+ min_wh, max_wh = 2, 4096
205
+ max_det = 300
206
+ max_nms = 30000
207
+ redundant = True
208
+ multi_label &= nc > 1
209
+ merge = False
210
+ output = [np.zeros((0,6))] * prediction.shape[0]
211
+
212
+ for xi, x in enumerate(prediction):
213
+ x = x[xc[xi]]
214
+ if labels and len(labels[xi]):
215
+ l = labels[xi]
216
+
217
+ v = np.zeros(len(l), nc + 5)
218
+ v[:, :4] = l[:, 1:5]
219
+ v[:, 4] = 1.0
220
+ v[range(len(l)), l[:, 0].long() + 5] = 1.0
221
+
222
+ x = np.concatenate((x, v), 0)
223
+ if not x.shape[0]:
224
+ continue
225
+
226
+ x[:, 5:5+nc] *= x[:, 4:5]
227
+ box = xywh2xyxy(x[:, :4])
228
+ if multi_label:
229
+ if not kpt_label:
230
+ i, j = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
231
+ x = np.concatenate((box[i], x[i, j + 5, None], j[:, None].float()), 1)
232
+ else:
233
+ kpts = x[:, 5+nc:]
234
+ i, j = (x[:, 5:5+nc] > conf_thres).nonzero(as_tuple=False).T
235
+ x = np.concatenate((box[i], x[i, j + 5, None], j[:, None].float(),kpts[i]), 1)
236
+ else:
237
+ if not kpt_label:
238
+ conf, j = x[:, 5:].max(1, keepdim=True)
239
+ x = np.concatenate((box, conf, j.float()), 1)[conf.view(-1) > conf_thres]
240
+ else:
241
+ kpts = x[:, 5+nc:]
242
+ conf = np.max(x[:, 5:5+nc], 1).reshape(box.shape[:1][0], 1)
243
+ j = np.argmax(x[:, 5:5+nc], 1).reshape(box.shape[:1][0], 1)
244
+ x = np.concatenate((box, conf, j, kpts), 1)[conf.reshape(box.shape[:1][0]) > conf_thres]
245
+
246
+ if classes is not None:
247
+ x = x[(x[:, 5:6] == np.array(classes, device=x.device)).any(1)]
248
+
249
+ n = x.shape[0]
250
+
251
+ if not n:
252
+ continue
253
+ elif n > max_nms:
254
+ x = x[x[:, 4].argsort(descending=True)[:max_nms]]
255
+
256
+ c = x[:, 5:6] * (0 if agnostic else max_wh)
257
+
258
+ boxes, scores = x[:, :4] + c, x[:, 4]
259
+
260
+ i = nms_boxes(boxes, scores)
261
+ if i.shape[0] > max_det:
262
+ i = i[:max_det]
263
+ if merge and (1 < n < 3E3):
264
+
265
+ iou = box_iou(boxes[i], boxes) > iou_thres
266
+ weights = iou * scores[None]
267
+ x[i, :4] = np.multiply(weights, x[:, :4]).float() / weights.sum(1, keepdim=True)
268
+
269
+ if redundant:
270
+ i = i[iou.sum(1) > 1]
271
+
272
+ output[xi] = x[i]
273
+
274
+ return output
275
+
276
+ def _make_grid(nx=20, ny=20):
277
+ y, x = np.arange(ny, dtype=np.float32), np.arange(nx, dtype=np.float32)
278
+
279
+ yv, xv = np.meshgrid(y, x, indexing='ij')
280
+ return np.stack((xv, yv), 2).reshape((1, 1, ny, nx, 2))
281
+
282
+ def sigmoid(x):
283
+ return 1 / (1 + np.exp(-x))
284
+
285
+ def preprocess(img_path, imgsz):
286
+ """预处理:读取图像并进行归一化"""
287
+ im0 = cv2.imread(img_path)
288
+ img = letterbox(im0, imgsz, auto=False, stride=32)[0]
289
+ img = np.ascontiguousarray(img[:, :, ::-1].transpose(2, 0, 1))
290
+ img = np.asarray(img, dtype=np.uint8)
291
+ img = np.expand_dims(img, 0)
292
+ return img, im0
293
+
294
+ def model_postprocess(preds, anchors, stride, names, nkpt, conf_thres, iou_thres):
295
+ """后处理:解码预测结果、NMS和坐标变换"""
296
+ na = len(anchors[0]) // 2
297
+ nl = len(anchors)
298
+ nc = len(names)
299
+ no = len(names) + 5 + nkpt * 3
300
+
301
+ z = []
302
+ for i, pred in enumerate(preds):
303
+ bs, _, ny, nx = pred.shape
304
+ pred = pred.reshape(bs, na, no, ny, nx).transpose(0, 1, 3, 4, 2)
305
+ pred_det = pred[..., :5+nc]
306
+ pred_kpt = pred[..., 5+nc:]
307
+ grid = _make_grid(nx, ny)
308
+ kpt_grid_x = grid[..., 0:1]
309
+ kpt_grid_y = grid[..., 1:2]
310
+
311
+ y = sigmoid(pred_det)
312
+
313
+ xy = (y[..., 0:2] * 2. - 0.5 + grid) * stride[i]
314
+ wh = (y[..., 2:4] * 2) ** 2 * np.array(anchors[i]).reshape(1, 3, 1, 1, 2)
315
+
316
+ pred_kpt[..., 0::3] = (pred_kpt[..., ::3] * 2. - 0.5 + np.tile(kpt_grid_x, (1,1,1,1,nkpt))) * stride[i]
317
+ pred_kpt[..., 1::3] = (pred_kpt[..., 1::3] * 2. - 0.5 + np.tile(kpt_grid_y, (1,1,1,1,nkpt))) * stride[i]
318
+ pred_kpt[..., 2::3] = sigmoid(pred_kpt[..., 2::3])
319
+ y = np.concatenate((xy, wh, y[..., 4:], pred_kpt), axis=-1)
320
+
321
+ z.append(y.reshape(bs, na * nx * ny, no))
322
+
323
+ preds = np.concatenate(z, 1)
324
+ preds = non_max_suppression(preds, conf_thres, iou_thres, nc=nc, nkpt=nkpt, kpt_label=True)
325
+
326
+ return preds
327
+
328
+ def draw_predictions(preds, img, im0, names, imgsz):
329
+ """绘制检测结果和关键点"""
330
+ for i, det in enumerate(preds):
331
+ if len(det):
332
+ scale_coords(imgsz, det[:, :4], im0.shape, kpt_label=False)
333
+ scale_coords(imgsz, det[:, 6:], im0.shape, kpt_label=True, step=3)
334
+
335
+ for det_index, (*xyxy, conf, cls) in enumerate(reversed(det[:, :6])):
336
+ print("class:",names[int(cls)], "left:%.0f" % xyxy[0],"top:%.0f" % xyxy[1],"right:%.0f" % xyxy[2],"bottom:%.0f" % xyxy[3], "conf:",'{:.0f}%'.format(float(conf)*100))
337
+ c = int(cls)
338
+ label = f'{names[c]} {conf:.2f}'
339
+ kpts = det[det_index, 6:]
340
+ plot_one_box(xyxy, im0, label=label, color=colors(c, True), line_thickness=2,
341
+ kpt_label=True, kpts=kpts, steps=3, orig_shape=im0.shape[:2])
342
+
343
+ return im0
344
+
345
+ if __name__ == "__main__":
346
+ parser = argparse.ArgumentParser(description='跌倒检测模型推理脚本')
347
+ parser.add_argument('--model', type=str, default='./fall_ax650_npu3.axmodel',
348
+ help='axmodel 模型路径')
349
+ parser.add_argument('--img', type=str, default='./fall4.png',
350
+ help='输入图像路径')
351
+ parser.add_argument('--output', type=str, default='axmodel_res.jpg',
352
+ help='输出结果图像路径')
353
+ parser.add_argument('--imgsz', type=int, nargs=2, default=[320, 480],
354
+ help='输入图像尺寸 (height width)')
355
+ parser.add_argument('--conf-thres', type=float, default=0.3,
356
+ help='置信度阈值')
357
+ parser.add_argument('--iou-thres', type=float, default=0.45,
358
+ help='IOU阈值')
359
+
360
+ args = parser.parse_args()
361
+
362
+ # model params
363
+ names = ['normal', 'fall']
364
+ anchors = [[30, 61, 55, 124, 90, 207], [149, 232, 128, 357, 221, 308]]
365
+ stride = [16, 32]
366
+ nkpt = 14
367
+ imgsz = tuple(args.imgsz)
368
+
369
+ img, im0 = preprocess(args.img, imgsz)
370
+
371
+ preds = model_inference(args.model, img)
372
+
373
+ preds = model_postprocess(preds, anchors, stride, names, nkpt, args.conf_thres, args.iou_thres)
374
+
375
+ im0 = draw_predictions(preds, img, im0, names, imgsz)
376
+
377
+ cv2.imwrite(args.output, im0)
378
+ print(f"Result saved to {args.output}")
axmodel_res.jpg ADDED

Git LFS Details

  • SHA256: ed3d9c2c79700e825fd049129b9228e9ef6f94dfefaac4a8b86f9cdb047a6f1e
  • Pointer size: 131 Bytes
  • Size of remote file: 172 kB
config.json ADDED
File without changes
fall4.png ADDED

Git LFS Details

  • SHA256: 5919910f56b047a3b697b95eb415e227de75738be7db92bab1d350a4d8de695b
  • Pointer size: 131 Bytes
  • Size of remote file: 668 kB