|
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+#!python3
|
|
|
2
|
+"""
|
|
|
3
|
+Python 3 wrapper for identifying objects in images
|
|
|
4
|
+
|
|
|
5
|
+Requires DLL compilation
|
|
|
6
|
+
|
|
|
7
|
+Original *nix 2.7: https://github.com/pjreddie/darknet/blob/0f110834f4e18b30d5f101bf8f1724c34b7b83db/python/darknet.py
|
|
|
8
|
+Windows Python 2.7 version: https://github.com/AlexeyAB/darknet/blob/fc496d52bf22a0bb257300d3c79be9cd80e722cb/build/darknet/x64/darknet.py
|
|
|
9
|
+
|
|
|
10
|
+@author: Philip Kahn, Aymeric Dujardin
|
|
|
11
|
+@date: 20180911
|
|
|
12
|
+"""
|
|
|
13
|
+# pylint: disable=R, W0401, W0614, W0703
|
|
|
14
|
+import cv2
|
|
|
15
|
+import pyzed.sl as sl
|
|
|
16
|
+from ctypes import *
|
|
|
17
|
+import math
|
|
|
18
|
+import random
|
|
|
19
|
+import os
|
|
|
20
|
+import numpy as np
|
|
|
21
|
+import statistics
|
|
|
22
|
+import sys
|
|
|
23
|
+import getopt
|
|
|
24
|
+from random import randint
|
|
|
25
|
+import time
|
|
|
26
|
+import pandas as pd
|
|
|
27
|
+from pandas import DataFrame as df
|
|
|
28
|
+import subprocess
|
|
|
29
|
+
|
|
|
30
|
+
|
|
|
31
|
+#NOTE at 2020-12-22: if svo's resulotion changed, then you have to edit WIDTH, HEIGHT and DEPTH_MAX
|
|
|
32
|
+WIDTH = 1920
|
|
|
33
|
+HEIGHT = 1080
|
|
|
34
|
+DEPTH_MAX = 8
|
|
|
35
|
+
|
|
|
36
|
+
|
|
|
37
|
+def sample(probs):
|
|
|
38
|
+ s = sum(probs)
|
|
|
39
|
+ probs = [a/s for a in probs]
|
|
|
40
|
+ r = random.uniform(0, 1)
|
|
|
41
|
+ for i in range(len(probs)):
|
|
|
42
|
+ r = r - probs[i]
|
|
|
43
|
+ if r <= 0:
|
|
|
44
|
+ return i
|
|
|
45
|
+ return len(probs)-1
|
|
|
46
|
+
|
|
|
47
|
+
|
|
|
48
|
+def c_array(ctype, values):
|
|
|
49
|
+ arr = (ctype*len(values))()
|
|
|
50
|
+ arr[:] = values
|
|
|
51
|
+ return arr
|
|
|
52
|
+
|
|
|
53
|
+
|
|
|
54
|
+class BOX(Structure):
|
|
|
55
|
+ _fields_ = [("x", c_float),
|
|
|
56
|
+ ("y", c_float),
|
|
|
57
|
+ ("w", c_float),
|
|
|
58
|
+ ("h", c_float)]
|
|
|
59
|
+
|
|
|
60
|
+
|
|
|
61
|
+class DETECTION(Structure):
|
|
|
62
|
+ _fields_ = [("bbox", BOX),
|
|
|
63
|
+ ("classes", c_int),
|
|
|
64
|
+ ("prob", POINTER(c_float)),
|
|
|
65
|
+ ("mask", POINTER(c_float)),
|
|
|
66
|
+ ("objectness", c_float),
|
|
|
67
|
+ ("sort_class", c_int)]
|
|
|
68
|
+
|
|
|
69
|
+
|
|
|
70
|
+class IMAGE(Structure):
|
|
|
71
|
+ _fields_ = [("w", c_int),
|
|
|
72
|
+ ("h", c_int),
|
|
|
73
|
+ ("c", c_int),
|
|
|
74
|
+ ("data", POINTER(c_float))]
|
|
|
75
|
+
|
|
|
76
|
+
|
|
|
77
|
+class METADATA(Structure):
|
|
|
78
|
+ _fields_ = [("classes", c_int),
|
|
|
79
|
+ ("names", POINTER(c_char_p))]
|
|
|
80
|
+
|
|
|
81
|
+
|
|
|
82
|
+#lib = CDLL("/home/pjreddie/documents/darknet/libdarknet.so", RTLD_GLOBAL)
|
|
|
83
|
+#lib = CDLL("darknet.so", RTLD_GLOBAL)
|
|
|
84
|
+hasGPU = True
|
|
|
85
|
+if os.name == "nt":
|
|
|
86
|
+ cwd = os.path.dirname(__file__)
|
|
|
87
|
+ os.environ['PATH'] = cwd + ';' + os.environ['PATH']
|
|
|
88
|
+ winGPUdll = os.path.join(cwd, "yolo_cpp_dll.dll")
|
|
|
89
|
+ #print(winGPUdll)
|
|
|
90
|
+ winNoGPUdll = os.path.join(cwd, "yolo_cpp_dll_nogpu.dll")
|
|
|
91
|
+ envKeys = list()
|
|
|
92
|
+ for k, v in os.environ.items():
|
|
|
93
|
+ envKeys.append(k)
|
|
|
94
|
+ try:
|
|
|
95
|
+ try:
|
|
|
96
|
+ tmp = os.environ["FORCE_CPU"].lower()
|
|
|
97
|
+ if tmp in ["1", "true", "yes", "on"]:
|
|
|
98
|
+ raise ValueError("ForceCPU")
|
|
|
99
|
+ else:
|
|
|
100
|
+ pass#print("Flag value '"+tmp+"' not forcing CPU mode")
|
|
|
101
|
+ except KeyError:
|
|
|
102
|
+ # We never set the flag
|
|
|
103
|
+ if 'CUDA_VISIBLE_DEVICES' in envKeys:
|
|
|
104
|
+ if int(os.environ['CUDA_VISIBLE_DEVICES']) < 0:
|
|
|
105
|
+ raise ValueError("ForceCPU")
|
|
|
106
|
+ try:
|
|
|
107
|
+ global DARKNET_FORCE_CPU
|
|
|
108
|
+ if DARKNET_FORCE_CPU:
|
|
|
109
|
+ raise ValueError("ForceCPU")
|
|
|
110
|
+ except NameError:
|
|
|
111
|
+ pass
|
|
|
112
|
+ # #print(os.environ.keys())
|
|
|
113
|
+ # #print("FORCE_CPU flag undefined, proceeding with GPU")
|
|
|
114
|
+ if not os.path.exists(winGPUdll):
|
|
|
115
|
+ raise ValueError("NoDLL")
|
|
|
116
|
+ lib = CDLL(winGPUdll, RTLD_GLOBAL)
|
|
|
117
|
+ except (KeyError, ValueError):
|
|
|
118
|
+ hasGPU = False
|
|
|
119
|
+ if os.path.exists(winNoGPUdll):
|
|
|
120
|
+ lib = CDLL(winNoGPUdll, RTLD_GLOBAL)
|
|
|
121
|
+ #print("Notice: CPU-only mode")
|
|
|
122
|
+ else:
|
|
|
123
|
+ # Try the other way, in case no_gpu was
|
|
|
124
|
+ # compile but not renamed
|
|
|
125
|
+ lib = CDLL(winGPUdll, RTLD_GLOBAL)
|
|
|
126
|
+ #print("Environment variables indicated a CPU run, but we didn't find `" +
|
|
|
127
|
+ # winNoGPUdll+"`. Trying a GPU run anyway.")
|
|
|
128
|
+else:
|
|
|
129
|
+ lib = CDLL("/root/darknet/libdarknet.so", RTLD_GLOBAL)
|
|
|
130
|
+lib.network_width.argtypes = [c_void_p]
|
|
|
131
|
+lib.network_width.restype = c_int
|
|
|
132
|
+lib.network_height.argtypes = [c_void_p]
|
|
|
133
|
+lib.network_height.restype = c_int
|
|
|
134
|
+
|
|
|
135
|
+predict = lib.network_predict
|
|
|
136
|
+predict.argtypes = [c_void_p, POINTER(c_float)]
|
|
|
137
|
+predict.restype = POINTER(c_float)
|
|
|
138
|
+
|
|
|
139
|
+if hasGPU:
|
|
|
140
|
+ set_gpu = lib.cuda_set_device
|
|
|
141
|
+ set_gpu.argtypes = [c_int]
|
|
|
142
|
+
|
|
|
143
|
+make_image = lib.make_image
|
|
|
144
|
+make_image.argtypes = [c_int, c_int, c_int]
|
|
|
145
|
+make_image.restype = IMAGE
|
|
|
146
|
+
|
|
|
147
|
+get_network_boxes = lib.get_network_boxes
|
|
|
148
|
+get_network_boxes.argtypes = [c_void_p, c_int, c_int, c_float, c_float, POINTER(
|
|
|
149
|
+ c_int), c_int, POINTER(c_int), c_int]
|
|
|
150
|
+get_network_boxes.restype = POINTER(DETECTION)
|
|
|
151
|
+
|
|
|
152
|
+make_network_boxes = lib.make_network_boxes
|
|
|
153
|
+make_network_boxes.argtypes = [c_void_p]
|
|
|
154
|
+make_network_boxes.restype = POINTER(DETECTION)
|
|
|
155
|
+
|
|
|
156
|
+free_detections = lib.free_detections
|
|
|
157
|
+free_detections.argtypes = [POINTER(DETECTION), c_int]
|
|
|
158
|
+
|
|
|
159
|
+free_ptrs = lib.free_ptrs
|
|
|
160
|
+free_ptrs.argtypes = [POINTER(c_void_p), c_int]
|
|
|
161
|
+
|
|
|
162
|
+network_predict = lib.network_predict
|
|
|
163
|
+network_predict.argtypes = [c_void_p, POINTER(c_float)]
|
|
|
164
|
+
|
|
|
165
|
+reset_rnn = lib.reset_rnn
|
|
|
166
|
+reset_rnn.argtypes = [c_void_p]
|
|
|
167
|
+
|
|
|
168
|
+load_net = lib.load_network
|
|
|
169
|
+load_net.argtypes = [c_char_p, c_char_p, c_int]
|
|
|
170
|
+load_net.restype = c_void_p
|
|
|
171
|
+
|
|
|
172
|
+load_net_custom = lib.load_network_custom
|
|
|
173
|
+load_net_custom.argtypes = [c_char_p, c_char_p, c_int, c_int]
|
|
|
174
|
+load_net_custom.restype = c_void_p
|
|
|
175
|
+
|
|
|
176
|
+do_nms_obj = lib.do_nms_obj
|
|
|
177
|
+do_nms_obj.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
|
|
|
178
|
+
|
|
|
179
|
+do_nms_sort = lib.do_nms_sort
|
|
|
180
|
+do_nms_sort.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
|
|
|
181
|
+
|
|
|
182
|
+free_image = lib.free_image
|
|
|
183
|
+free_image.argtypes = [IMAGE]
|
|
|
184
|
+
|
|
|
185
|
+letterbox_image = lib.letterbox_image
|
|
|
186
|
+letterbox_image.argtypes = [IMAGE, c_int, c_int]
|
|
|
187
|
+letterbox_image.restype = IMAGE
|
|
|
188
|
+
|
|
|
189
|
+load_meta = lib.get_metadata
|
|
|
190
|
+lib.get_metadata.argtypes = [c_char_p]
|
|
|
191
|
+lib.get_metadata.restype = METADATA
|
|
|
192
|
+
|
|
|
193
|
+load_image = lib.load_image_color
|
|
|
194
|
+load_image.argtypes = [c_char_p, c_int, c_int]
|
|
|
195
|
+load_image.restype = IMAGE
|
|
|
196
|
+
|
|
|
197
|
+rgbgr_image = lib.rgbgr_image
|
|
|
198
|
+rgbgr_image.argtypes = [IMAGE]
|
|
|
199
|
+
|
|
|
200
|
+predict_image = lib.network_predict_image
|
|
|
201
|
+predict_image.argtypes = [c_void_p, IMAGE]
|
|
|
202
|
+predict_image.restype = POINTER(c_float)
|
|
|
203
|
+
|
|
|
204
|
+
|
|
|
205
|
+def array_to_image(arr):
|
|
|
206
|
+ import numpy as np
|
|
|
207
|
+ # need to return old values to avoid python freeing memory
|
|
|
208
|
+ arr = arr.transpose(2, 0, 1)
|
|
|
209
|
+ c = arr.shape[0]
|
|
|
210
|
+ h = arr.shape[1]
|
|
|
211
|
+ w = arr.shape[2]
|
|
|
212
|
+ arr = np.ascontiguousarray(arr.flat, dtype=np.float32) / 255.0
|
|
|
213
|
+ data = arr.ctypes.data_as(POINTER(c_float))
|
|
|
214
|
+ im = IMAGE(w, h, c, data)
|
|
|
215
|
+ return im, arr
|
|
|
216
|
+
|
|
|
217
|
+
|
|
|
218
|
+def classify(net, meta, im):
|
|
|
219
|
+ out = predict_image(net, im)
|
|
|
220
|
+ res = []
|
|
|
221
|
+ for i in range(meta.classes):
|
|
|
222
|
+ if altNames is None:
|
|
|
223
|
+ nameTag = meta.names[i]
|
|
|
224
|
+ else:
|
|
|
225
|
+ nameTag = altNames[i]
|
|
|
226
|
+ res.append((nameTag, out[i]))
|
|
|
227
|
+ res = sorted(res, key=lambda x: -x[1])
|
|
|
228
|
+ return res
|
|
|
229
|
+
|
|
|
230
|
+
|
|
|
231
|
+def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45, debug=False):
|
|
|
232
|
+ """
|
|
|
233
|
+ Performs the detection
|
|
|
234
|
+ """
|
|
|
235
|
+ custom_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
|
|
236
|
+ custom_image = cv2.resize(custom_image, (lib.network_width(
|
|
|
237
|
+ net), lib.network_height(net)), interpolation=cv2.INTER_LINEAR)
|
|
|
238
|
+ im, arr = array_to_image(custom_image)
|
|
|
239
|
+ num = c_int(0)
|
|
|
240
|
+ pnum = pointer(num)
|
|
|
241
|
+ predict_image(net, im)
|
|
|
242
|
+ dets = get_network_boxes(
|
|
|
243
|
+ net, image.shape[1], image.shape[0], thresh, hier_thresh, None, 0, pnum, 0)
|
|
|
244
|
+ num = pnum[0]
|
|
|
245
|
+ if nms:
|
|
|
246
|
+ do_nms_sort(dets, num, meta.classes, nms)
|
|
|
247
|
+ res = []
|
|
|
248
|
+ if debug:
|
|
|
249
|
+ pass
|
|
|
250
|
+ #print("about to range")
|
|
|
251
|
+ for j in range(num):
|
|
|
252
|
+ for i in range(meta.classes):
|
|
|
253
|
+ try:
|
|
|
254
|
+ if dets[j].prob[i] > 0:
|
|
|
255
|
+ b = dets[j].bbox
|
|
|
256
|
+ if altNames is None:
|
|
|
257
|
+ nameTag = meta.names[i]
|
|
|
258
|
+ else:
|
|
|
259
|
+ nameTag = altNames[i]
|
|
|
260
|
+ res.append((nameTag, dets[j].prob[i], (b.x, b.y, b.w, b.h), i))
|
|
|
261
|
+ except ValueError as e:
|
|
|
262
|
+ #print(e)
|
|
|
263
|
+ pass
|
|
|
264
|
+ res = sorted(res, key=lambda x: -x[1])
|
|
|
265
|
+ free_detections(dets, num)
|
|
|
266
|
+ return res
|
|
|
267
|
+
|
|
|
268
|
+
|
|
|
269
|
+netMain = None
|
|
|
270
|
+metaMain = None
|
|
|
271
|
+altNames = None
|
|
|
272
|
+
|
|
|
273
|
+
|
|
|
274
|
+def getObjectDepth(depth, bounds):
|
|
|
275
|
+ area_div = 2
|
|
|
276
|
+
|
|
|
277
|
+ x_vect = []
|
|
|
278
|
+ y_vect = []
|
|
|
279
|
+ z_vect = []
|
|
|
280
|
+
|
|
|
281
|
+ for j in range(int(bounds[0] - area_div), int(bounds[0] + area_div)):
|
|
|
282
|
+ for i in range(int(bounds[1] - area_div), int(bounds[1] + area_div)):
|
|
|
283
|
+ z = depth[i, j, 2]
|
|
|
284
|
+ if not np.isnan(z) and not np.isinf(z):
|
|
|
285
|
+ x_vect.append(depth[i, j, 0])
|
|
|
286
|
+ y_vect.append(depth[i, j, 1])
|
|
|
287
|
+ z_vect.append(z)
|
|
|
288
|
+ try:
|
|
|
289
|
+ x = statistics.median(x_vect)
|
|
|
290
|
+ y = statistics.median(y_vect)
|
|
|
291
|
+ z = statistics.median(z_vect)
|
|
|
292
|
+ except Exception:
|
|
|
293
|
+ x = -1
|
|
|
294
|
+ y = -1
|
|
|
295
|
+ z = -1
|
|
|
296
|
+ pass
|
|
|
297
|
+
|
|
|
298
|
+ return x, y, z
|
|
|
299
|
+
|
|
|
300
|
+
|
|
|
301
|
+def generateColor(metaPath):
|
|
|
302
|
+ random.seed(42)
|
|
|
303
|
+ f = open(metaPath, 'r')
|
|
|
304
|
+ content = f.readlines()
|
|
|
305
|
+ class_num = int(content[0].split("=")[1])
|
|
|
306
|
+ color_array = []
|
|
|
307
|
+ for x in range(0, class_num):
|
|
|
308
|
+ color_array.append((randint(0, 255), randint(0, 255), randint(0, 255)))
|
|
|
309
|
+ return color_array
|
|
|
310
|
+
|
|
|
311
|
+
|
|
|
312
|
+def main(argv):
|
|
|
313
|
+
|
|
|
314
|
+ thresh = 0.25
|
|
|
315
|
+ configPath = "/sources/cfg.cfg"
|
|
|
316
|
+ weightPath = "/sources/mailsys.weight"
|
|
|
317
|
+ metaPath = "/sources/data.data"
|
|
|
318
|
+ svoPath = None
|
|
|
319
|
+
|
|
|
320
|
+ help_str = 'darknet_zed.py -c <config> -w <weight> -m <meta> -t <threshold> -s <svo_file> -o <output_path>'
|
|
|
321
|
+ try:
|
|
|
322
|
+ opts, args = getopt.getopt(
|
|
|
323
|
+ argv, "hc:w:m:t:s:o:", ["config=", "weight=", "meta=", "threshold=", "svo_file=", "output_path="])
|
|
|
324
|
+ except getopt.GetoptError:
|
|
|
325
|
+ print (help_str)
|
|
|
326
|
+ sys.exit(2)
|
|
|
327
|
+ for opt, arg in opts:
|
|
|
328
|
+ if opt == '-h':
|
|
|
329
|
+ print (help_str)
|
|
|
330
|
+ sys.exit()
|
|
|
331
|
+ elif opt in ("-c", "--config"):
|
|
|
332
|
+ configPath = arg
|
|
|
333
|
+ elif opt in ("-w", "--weight"):
|
|
|
334
|
+ weightPath = arg
|
|
|
335
|
+ elif opt in ("-m", "--meta"):
|
|
|
336
|
+ metaPath = arg
|
|
|
337
|
+ elif opt in ("-t", "--threshold"):
|
|
|
338
|
+ thresh = float(arg)
|
|
|
339
|
+ elif opt in ("-s", "--svo_file"):
|
|
|
340
|
+ svoPath = arg
|
|
|
341
|
+ elif opt in ("-o", "--output_path"):
|
|
|
342
|
+ output_path = arg
|
|
|
343
|
+
|
|
|
344
|
+ init = sl.InitParameters()
|
|
|
345
|
+ init.coordinate_units = sl.UNIT.METER
|
|
|
346
|
+
|
|
|
347
|
+
|
|
|
348
|
+
|
|
|
349
|
+ if svoPath is not None:
|
|
|
350
|
+ init.set_from_svo_file(svoPath)
|
|
|
351
|
+
|
|
|
352
|
+ dirname = os.path.splitext(svoPath)[0]
|
|
|
353
|
+ dir, filename = os.path.split(dirname)
|
|
|
354
|
+ #print(output_path)
|
|
|
355
|
+ #print(filename)
|
|
|
356
|
+
|
|
|
357
|
+ #try:
|
|
|
358
|
+ # if not (os.path.isdir(output_path)):
|
|
|
359
|
+ # os.makedirs(os.path.join(output_path))
|
|
|
360
|
+ #except OSError as e:
|
|
|
361
|
+ # #print(e)
|
|
|
362
|
+
|
|
|
363
|
+
|
|
|
364
|
+ cam = sl.Camera()
|
|
|
365
|
+ if not cam.is_opened():
|
|
|
366
|
+ #print("Opening ZED Camera...")
|
|
|
367
|
+ pass
|
|
|
368
|
+ status = cam.open(init)
|
|
|
369
|
+ if status != sl.ERROR_CODE.SUCCESS:
|
|
|
370
|
+ #print(repr(status))
|
|
|
371
|
+ exit()
|
|
|
372
|
+
|
|
|
373
|
+ runtime = sl.RuntimeParameters()
|
|
|
374
|
+ # Use STANDARD sensing mode
|
|
|
375
|
+ runtime.sensing_mode = sl.SENSING_MODE.STANDARD
|
|
|
376
|
+ mat = sl.Mat()
|
|
|
377
|
+ point_cloud_mat = sl.Mat()
|
|
|
378
|
+
|
|
|
379
|
+ # Import the global variables. This lets us instance Darknet once, then just call performDetect() again without instancing again
|
|
|
380
|
+ global metaMain, netMain, altNames # pylint: disable=W0603
|
|
|
381
|
+ assert 0 < thresh < 1, "Threshold should be a float between zero and one (non-inclusive)"
|
|
|
382
|
+ if not os.path.exists(configPath):
|
|
|
383
|
+ raise ValueError("Invalid config path `" +
|
|
|
384
|
+ os.path.abspath(configPath)+"`")
|
|
|
385
|
+ if not os.path.exists(weightPath):
|
|
|
386
|
+ raise ValueError("Invalid weight path `" +
|
|
|
387
|
+ os.path.abspath(weightPath)+"`")
|
|
|
388
|
+ if not os.path.exists(metaPath):
|
|
|
389
|
+ raise ValueError("Invalid data file path `" +
|
|
|
390
|
+ os.path.abspath(metaPath)+"`")
|
|
|
391
|
+ if netMain is None:
|
|
|
392
|
+ netMain = load_net_custom(configPath.encode(
|
|
|
393
|
+ "ascii"), weightPath.encode("ascii"), 0, 1) # batch size = 1
|
|
|
394
|
+ if metaMain is None:
|
|
|
395
|
+ metaMain = load_meta(metaPath.encode("ascii"))
|
|
|
396
|
+ if altNames is None:
|
|
|
397
|
+ # In thon 3, the metafile default access craps out on Windows (but not Linux)
|
|
|
398
|
+ # Read the names file and create a list to feed to detect
|
|
|
399
|
+ try:
|
|
|
400
|
+ with open(metaPath) as metaFH:
|
|
|
401
|
+ metaContents = metaFH.read()
|
|
|
402
|
+ import re
|
|
|
403
|
+ match = re.search("names *= *(.*)$", metaContents,
|
|
|
404
|
+ re.IGNORECASE | re.MULTILINE)
|
|
|
405
|
+ if match:
|
|
|
406
|
+ result = match.group(1)
|
|
|
407
|
+ else:
|
|
|
408
|
+ result = None
|
|
|
409
|
+ try:
|
|
|
410
|
+ if os.path.exists(result):
|
|
|
411
|
+ with open(result) as namesFH:
|
|
|
412
|
+ namesList = namesFH.read().strip().split("\n")
|
|
|
413
|
+ altNames = [x.strip() for x in namesList]
|
|
|
414
|
+ except TypeError:
|
|
|
415
|
+ pass
|
|
|
416
|
+ except Exception:
|
|
|
417
|
+ pass
|
|
|
418
|
+
|
|
|
419
|
+ color_array = generateColor(metaPath)
|
|
|
420
|
+
|
|
|
421
|
+ #print("Running...")
|
|
|
422
|
+ #df1 = df(data={'frame': [], 'label': [], 'x': [], 'y': [], 'depth': []})
|
|
|
423
|
+ df1 = df(data={'x': [], 'y': [], 'z': [], 'frame': []})
|
|
|
424
|
+ #print(df1)
|
|
|
425
|
+ start = time.time()
|
|
|
426
|
+ key = ''
|
|
|
427
|
+ count = 0
|
|
|
428
|
+ frame = 1
|
|
|
429
|
+
|
|
|
430
|
+ #image_size = cam.get_resolution()
|
|
|
431
|
+ #width = image_size.width
|
|
|
432
|
+ #height = image_size.height
|
|
|
433
|
+ #width_sbs = width * 2
|
|
|
434
|
+
|
|
|
435
|
+ # Prepare side by side image container equivalent to CV_8UC4
|
|
|
436
|
+ #svo_image_sbs_rgba = np.zeros((height, width_sbs, 4), dtype=np.uint8)
|
|
|
437
|
+ fourcc = cv2.VideoWriter_fourcc('M', '4', 'S', '2')
|
|
|
438
|
+
|
|
|
439
|
+ # 컬러 영상 저장시
|
|
|
440
|
+ ##print(cam.get_camera_fps(), "!!!!!!!!!!!")
|
|
|
441
|
+ #video_path = os.path.join(output_path, filename)
|
|
|
442
|
+ #writer = cv2.VideoWriter(str(video_path)+"_output.avi", fourcc, cam.get_camera_fps(), (width, height))
|
|
|
443
|
+ ##print(video_path)
|
|
|
444
|
+ ##print(writer)
|
|
|
445
|
+ while key != 113: # for 'q' key
|
|
|
446
|
+ err = cam.grab(runtime)
|
|
|
447
|
+ if err == sl.ERROR_CODE.SUCCESS:
|
|
|
448
|
+ cam.retrieve_image(mat, sl.VIEW.LEFT)
|
|
|
449
|
+ image = mat.get_data()
|
|
|
450
|
+
|
|
|
451
|
+ cam.retrieve_measure(
|
|
|
452
|
+ point_cloud_mat, sl.MEASURE.XYZRGBA)
|
|
|
453
|
+ depth = point_cloud_mat.get_data()
|
|
|
454
|
+
|
|
|
455
|
+ # Do the detection
|
|
|
456
|
+ detections = detect(netMain, metaMain, image, thresh)
|
|
|
457
|
+
|
|
|
458
|
+ #print(chr(27) + "[2J"+"**** " +
|
|
|
459
|
+ # str(len(detections)) + " Results ****")
|
|
|
460
|
+ frame += 1
|
|
|
461
|
+ for detection in detections:
|
|
|
462
|
+ label = detection[0]
|
|
|
463
|
+ confidence = detection[1]
|
|
|
464
|
+ pstring = label+": "+str(np.rint(100 * confidence))+"%"
|
|
|
465
|
+ #print(pstring)
|
|
|
466
|
+ bounds = detection[2]
|
|
|
467
|
+ yExtent = int(bounds[3])
|
|
|
468
|
+ xEntent = int(bounds[2])
|
|
|
469
|
+ # Coordinates are around the center
|
|
|
470
|
+ xCoord = int(bounds[0] - bounds[2]/2)
|
|
|
471
|
+ yCoord = int(bounds[1] - bounds[3]/2)
|
|
|
472
|
+ boundingBox = [[xCoord, yCoord], [xCoord, yCoord + yExtent], [xCoord + xEntent, yCoord + yExtent], [xCoord + xEntent, yCoord] ]
|
|
|
473
|
+ thickness = 1
|
|
|
474
|
+ x, y, z = getObjectDepth(depth, bounds)
|
|
|
475
|
+ distance_xyz = math.sqrt(x * x + y * y + z * z)
|
|
|
476
|
+
|
|
|
477
|
+ distance = "{:.4f}".format(distance_xyz)
|
|
|
478
|
+
|
|
|
479
|
+ #print(label, distance, xCoord, yCoord)
|
|
|
480
|
+ cv2.rectangle(image, (xCoord-thickness, yCoord-thickness), (xCoord + xEntent+thickness, yCoord+(18 +thickness*4)), color_array[detection[3]], -1)
|
|
|
481
|
+ cv2.putText(image, label + " " + (str(distance) + " m"), (xCoord+(thickness*4), yCoord+(10 +thickness*4)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)
|
|
|
482
|
+ cv2.rectangle(image, (xCoord-thickness, yCoord-thickness), (xCoord + xEntent+thickness, yCoord + yExtent+thickness), color_array[detection[3]], int(thickness*2))
|
|
|
483
|
+ x = xCoord-thickness
|
|
|
484
|
+ x1 = xCoord + xEntent+thickness
|
|
|
485
|
+ y = yCoord-thickness
|
|
|
486
|
+ y1 = yCoord + yExtent+thickness
|
|
|
487
|
+
|
|
|
488
|
+
|
|
|
489
|
+ #If need normalize, erase # and change df1.loc[count]
|
|
|
490
|
+ #norm_x = (x + x1) / 2 / WIDTH
|
|
|
491
|
+ #norm_y = (y + y1) / 2 / HEIGHT
|
|
|
492
|
+ #norm_z = distance_xyz / DEPTH_MAX
|
|
|
493
|
+
|
|
|
494
|
+
|
|
|
495
|
+
|
|
|
496
|
+ df1.loc[count] = [int(xCoord), int(yCoord), distance_xyz, int(frame)]
|
|
|
497
|
+ #df1.columns = ['idx','frame','label','x','y','depth']
|
|
|
498
|
+ cv2.line(image, (int((x+x1)/2), int((y+y1)/2)), (int((x+x1)/2), int((y+y1)/2)), (0, 0, 255), 10)
|
|
|
499
|
+
|
|
|
500
|
+ count += 1
|
|
|
501
|
+ image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
|
|
|
502
|
+ #print(frame)
|
|
|
503
|
+ image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
|
|
|
504
|
+ #writer.write(image)
|
|
|
505
|
+ # cv2.imshow("ZED", image)
|
|
|
506
|
+ # key = cv2.waitKey(5)
|
|
|
507
|
+ # #print(cam.get_svo_number_of_frames())
|
|
|
508
|
+ if frame == cam.get_svo_number_of_frames():
|
|
|
509
|
+ break
|
|
|
510
|
+ else:
|
|
|
511
|
+ #print('something happend')
|
|
|
512
|
+ #key = cv2.waitKey(5)
|
|
|
513
|
+ pass
|
|
|
514
|
+ #print("time :", time.time() - start)
|
|
|
515
|
+
|
|
|
516
|
+ cam.close()
|
|
|
517
|
+ #writer.release()
|
|
|
518
|
+ #cv2.destroyAllWindows()
|
|
|
519
|
+ #print("\nFINISH")
|
|
|
520
|
+ ##print(df1)
|
|
|
521
|
+
|
|
|
522
|
+ df1.to_csv(output_path, index=False)
|
|
|
523
|
+ #print("csv save")
|
|
|
524
|
+
|
|
|
525
|
+
|
|
|
526
|
+if __name__ == "__main__":
|
|
|
527
|
+
|
|
|
528
|
+ #print(sys.argv)
|
|
|
529
|
+ main(sys.argv[1:])
|