Repository for M.A.I.L system's analysis server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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