DanialAhmed

darknet.py

Dec 11th, 2019
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.07 KB | None | 0 0
  1. #!python3
  2. """
  3. Python 3 wrapper for identifying objects in images
  4.  
  5. Requires DLL compilation
  6.  
  7. Both the GPU and no-GPU version should be compiled; the no-GPU version should be renamed "yolo_cpp_dll_nogpu.dll".
  8.  
  9. On a GPU system, you can force CPU evaluation by any of:
  10.  
  11. - Set global variable DARKNET_FORCE_CPU to True
  12. - Set environment variable CUDA_VISIBLE_DEVICES to -1
  13. - Set environment variable "FORCE_CPU" to "true"
  14.  
  15.  
  16. To use, either run performDetect() after import, or modify the end of this file.
  17.  
  18. See the docstring of performDetect() for parameters.
  19.  
  20. Directly viewing or returning bounding-boxed images requires scikit-image to be installed (`pip install scikit-image`)
  21.  
  22.  
  23. Original *nix 2.7: https://github.com/pjreddie/darknet/blob/0f110834f4e18b30d5f101bf8f1724c34b7b83db/python/darknet.py
  24. Windows Python 2.7 version: https://github.com/AlexeyAB/darknet/blob/fc496d52bf22a0bb257300d3c79be9cd80e722cb/build/darknet/x64/darknet.py
  25.  
  26. @author: Philip Kahn
  27. @date: 20180503
  28. """
  29. #pylint: disable=R, W0401, W0614, W0703
  30. from ctypes import *
  31. import math
  32. import random
  33. import os
  34. import sys
  35. sys.path.insert(0,"C:\\darknet")
  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. def c_array(ctype, values):
  48. arr = (ctype*len(values))()
  49. arr[:] = values
  50. return arr
  51.  
  52. class BOX(Structure):
  53. _fields_ = [("x", c_float),
  54. ("y", c_float),
  55. ("w", c_float),
  56. ("h", c_float)]
  57.  
  58. class DETECTION(Structure):
  59. _fields_ = [("bbox", BOX),
  60. ("classes", c_int),
  61. ("prob", POINTER(c_float)),
  62. ("mask", POINTER(c_float)),
  63. ("objectness", c_float),
  64. ("sort_class", c_int),
  65. ("uc", POINTER(c_float)),
  66. ("points", c_int)]
  67.  
  68.  
  69. class IMAGE(Structure):
  70. _fields_ = [("w", c_int),
  71. ("h", c_int),
  72. ("c", c_int),
  73. ("data", POINTER(c_float))]
  74.  
  75. class METADATA(Structure):
  76. _fields_ = [("classes", c_int),
  77. ("names", POINTER(c_char_p))]
  78.  
  79.  
  80.  
  81. #lib = CDLL("/home/pjreddie/documents/darknet/libdarknet.so", RTLD_GLOBAL)
  82. #lib = CDLL("libdarknet.so", RTLD_GLOBAL)
  83. hasGPU = True
  84. if os.name == "nt":
  85. cwd = os.path.dirname(__file__)
  86. os.environ['PATH'] = cwd + ';' + os.environ['PATH']
  87. winGPUdll = os.path.join(cwd, "yolo_cpp_dll.dll")
  88. winNoGPUdll = os.path.join(cwd, "yolo_cpp_dll_nogpu.dll")
  89. envKeys = list()
  90. for k, v in os.environ.items():
  91. envKeys.append(k)
  92. try:
  93. try:
  94. tmp = os.environ["FORCE_CPU"].lower()
  95. if tmp in ["1", "true", "yes", "on"]:
  96. raise ValueError("ForceCPU")
  97. else:
  98. print("Flag value '"+tmp+"' not forcing CPU mode")
  99. except KeyError:
  100. # We never set the flag
  101. if 'CUDA_VISIBLE_DEVICES' in envKeys:
  102. if int(os.environ['CUDA_VISIBLE_DEVICES']) < 0:
  103. raise ValueError("ForceCPU")
  104. try:
  105. global DARKNET_FORCE_CPU
  106. if DARKNET_FORCE_CPU:
  107. raise ValueError("ForceCPU")
  108. except NameError:
  109. pass
  110. # print(os.environ.keys())
  111. # print("FORCE_CPU flag undefined, proceeding with GPU")
  112. if not os.path.exists(winGPUdll):
  113. raise ValueError("NoDLL")
  114. lib = CDLL(winGPUdll, RTLD_GLOBAL)
  115. except (KeyError, ValueError):
  116. hasGPU = False
  117. if os.path.exists(winNoGPUdll):
  118. lib = CDLL(winNoGPUdll, RTLD_GLOBAL)
  119. print("Notice: CPU-only mode")
  120. else:
  121. # Try the other way, in case no_gpu was
  122. # compile but not renamed
  123. lib = CDLL(winGPUdll, RTLD_GLOBAL)
  124. print("Environment variables indicated a CPU run, but we didn't find `"+winNoGPUdll+"`. Trying a GPU run anyway.")
  125. else:
  126. lib = CDLL("./libdarknet.so", RTLD_GLOBAL)
  127. lib.network_width.argtypes = [c_void_p]
  128. lib.network_width.restype = c_int
  129. lib.network_height.argtypes = [c_void_p]
  130. lib.network_height.restype = c_int
  131.  
  132. copy_image_from_bytes = lib.copy_image_from_bytes
  133. copy_image_from_bytes.argtypes = [IMAGE,c_char_p]
  134.  
  135. def network_width(net):
  136. return lib.network_width(net)
  137.  
  138. def network_height(net):
  139. return lib.network_height(net)
  140.  
  141. predict = lib.network_predict_ptr
  142. predict.argtypes = [c_void_p, POINTER(c_float)]
  143. predict.restype = POINTER(c_float)
  144.  
  145. if hasGPU:
  146. set_gpu = lib.cuda_set_device
  147. set_gpu.argtypes = [c_int]
  148.  
  149. init_cpu = lib.init_cpu
  150.  
  151. make_image = lib.make_image
  152. make_image.argtypes = [c_int, c_int, c_int]
  153. make_image.restype = IMAGE
  154.  
  155. get_network_boxes = lib.get_network_boxes
  156. get_network_boxes.argtypes = [c_void_p, c_int, c_int, c_float, c_float, POINTER(c_int), c_int, POINTER(c_int), c_int]
  157. get_network_boxes.restype = POINTER(DETECTION)
  158.  
  159. make_network_boxes = lib.make_network_boxes
  160. make_network_boxes.argtypes = [c_void_p]
  161. make_network_boxes.restype = POINTER(DETECTION)
  162.  
  163. free_detections = lib.free_detections
  164. free_detections.argtypes = [POINTER(DETECTION), c_int]
  165.  
  166. free_ptrs = lib.free_ptrs
  167. free_ptrs.argtypes = [POINTER(c_void_p), c_int]
  168.  
  169. network_predict = lib.network_predict_ptr
  170. network_predict.argtypes = [c_void_p, POINTER(c_float)]
  171.  
  172. reset_rnn = lib.reset_rnn
  173. reset_rnn.argtypes = [c_void_p]
  174.  
  175. load_net = lib.load_network
  176. load_net.argtypes = [c_char_p, c_char_p, c_int]
  177. load_net.restype = c_void_p
  178.  
  179. load_net_custom = lib.load_network_custom
  180. load_net_custom.argtypes = [c_char_p, c_char_p, c_int, c_int]
  181. load_net_custom.restype = c_void_p
  182.  
  183. do_nms_obj = lib.do_nms_obj
  184. do_nms_obj.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
  185.  
  186. do_nms_sort = lib.do_nms_sort
  187. do_nms_sort.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
  188.  
  189. free_image = lib.free_image
  190. free_image.argtypes = [IMAGE]
  191.  
  192. letterbox_image = lib.letterbox_image
  193. letterbox_image.argtypes = [IMAGE, c_int, c_int]
  194. letterbox_image.restype = IMAGE
  195.  
  196. load_meta = lib.get_metadata
  197. lib.get_metadata.argtypes = [c_char_p]
  198. lib.get_metadata.restype = METADATA
  199.  
  200. load_image = lib.load_image_color
  201. load_image.argtypes = [c_char_p, c_int, c_int]
  202. load_image.restype = IMAGE
  203.  
  204. rgbgr_image = lib.rgbgr_image
  205. rgbgr_image.argtypes = [IMAGE]
  206.  
  207. predict_image = lib.network_predict_image
  208. predict_image.argtypes = [c_void_p, IMAGE]
  209. predict_image.restype = POINTER(c_float)
  210.  
  211. predict_image_letterbox = lib.network_predict_image_letterbox
  212. predict_image_letterbox.argtypes = [c_void_p, IMAGE]
  213. predict_image_letterbox.restype = POINTER(c_float)
  214.  
  215. def array_to_image(arr):
  216. import numpy as np
  217. # need to return old values to avoid python freeing memory
  218. arr = arr.transpose(2,0,1)
  219. c = arr.shape[0]
  220. h = arr.shape[1]
  221. w = arr.shape[2]
  222. arr = np.ascontiguousarray(arr.flat, dtype=np.float32) / 255.0
  223. data = arr.ctypes.data_as(POINTER(c_float))
  224. im = IMAGE(w,h,c,data)
  225. return im, arr
  226.  
  227. def classify(net, meta, im):
  228. out = predict_image(net, im)
  229. res = []
  230. for i in range(meta.classes):
  231. if altNames is None:
  232. nameTag = meta.names[i]
  233. else:
  234. nameTag = altNames[i]
  235. res.append((nameTag, out[i]))
  236. res = sorted(res, key=lambda x: -x[1])
  237. return res
  238.  
  239. def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45, debug= False):
  240. """
  241. Performs the meat of the detection
  242. """
  243. #pylint: disable= C0321
  244. im = load_image(image, 0, 0)
  245. if debug: print("Loaded image")
  246. ret = detect_image(net, meta, im, thresh, hier_thresh, nms, debug)
  247. free_image(im)
  248. if debug: print("freed image")
  249. return ret
  250.  
  251. def detect_image(net, meta, im, thresh=.5, hier_thresh=.5, nms=.45, debug= False):
  252. #import cv2
  253. #custom_image_bgr = cv2.imread(image) # use: detect(,,imagePath,)
  254. #custom_image = cv2.cvtColor(custom_image_bgr, cv2.COLOR_BGR2RGB)
  255. #custom_image = cv2.resize(custom_image,(lib.network_width(net), lib.network_height(net)), interpolation = cv2.INTER_LINEAR)
  256. #import scipy.misc
  257. #custom_image = scipy.misc.imread(image)
  258. #im, arr = array_to_image(custom_image) # you should comment line below: free_image(im)
  259. num = c_int(0)
  260. if debug: print("Assigned num")
  261. pnum = pointer(num)
  262. if debug: print("Assigned pnum")
  263. predict_image(net, im)
  264. letter_box = 0
  265. #predict_image_letterbox(net, im)
  266. #letter_box = 1
  267. if debug: print("did prediction")
  268. #dets = get_network_boxes(net, custom_image_bgr.shape[1], custom_image_bgr.shape[0], thresh, hier_thresh, None, 0, pnum, letter_box) # OpenCV
  269. dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, None, 0, pnum, letter_box)
  270. if debug: print("Got dets")
  271. num = pnum[0]
  272. if debug: print("got zeroth index of pnum")
  273. if nms:
  274. do_nms_sort(dets, num, meta.classes, nms)
  275. if debug: print("did sort")
  276. res = []
  277. if debug: print("about to range")
  278. for j in range(num):
  279. if debug: print("Ranging on "+str(j)+" of "+str(num))
  280. if debug: print("Classes: "+str(meta), meta.classes, meta.names)
  281. for i in range(meta.classes):
  282. if debug: print("Class-ranging on "+str(i)+" of "+str(meta.classes)+"= "+str(dets[j].prob[i]))
  283. if dets[j].prob[i] > 0:
  284. b = dets[j].bbox
  285. if altNames is None:
  286. nameTag = meta.names[i]
  287. else:
  288. nameTag = altNames[i]
  289. if debug:
  290. print("Got bbox", b)
  291. print(nameTag)
  292. print(dets[j].prob[i])
  293. print((b.x, b.y, b.w, b.h))
  294. res.append((nameTag, dets[j].prob[i], (b.x, b.y, b.w, b.h)))
  295. if debug: print("did range")
  296. res = sorted(res, key=lambda x: -x[1])
  297. if debug: print("did sort")
  298. free_detections(dets, num)
  299. if debug: print("freed detections")
  300. return res
  301.  
  302.  
  303. netMain = None
  304. metaMain = None
  305. altNames = None
  306.  
  307. def performDetect(imagePath="data/dog.jpg", thresh= 0.25, configPath = "C:\\darknet\\cfg\obj.cfg", weightPath = "C:\\darknet\\obj_14000.weights", metaPath= "C:\\darknet\\cfg\\obj.data", showImage= True, makeImageOnly = False, initOnly= False):
  308. # Import the global variables. This lets us instance Darknet once, then just call performDetect() again without instancing again
  309. check=0
  310. global metaMain, netMain, altNames #pylint: disable=W0603
  311. assert 0 < thresh < 1, "Threshold should be a float between zero and one (non-inclusive)"
  312. if not os.path.exists(configPath):
  313. raise ValueError("Invalid config path `"+os.path.abspath(configPath)+"`")
  314. if not os.path.exists(weightPath):
  315. raise ValueError("Invalid weight path `"+os.path.abspath(weightPath)+"`")
  316. if not os.path.exists(metaPath):
  317. raise ValueError("Invalid data file path `"+os.path.abspath(metaPath)+"`")
  318. if netMain is None:
  319. netMain = load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1) # batch size = 1
  320. if metaMain is None:
  321. metaMain = load_meta(metaPath.encode("ascii"))
  322. if altNames is None:
  323. # In Python 3, the metafile default access craps out on Windows (but not Linux)
  324. # Read the names file and create a list to feed to detect
  325. try:
  326. with open(metaPath) as metaFH:
  327. metaContents = metaFH.read()
  328. import re
  329. match = re.search("names *= *(.*)$", metaContents, re.IGNORECASE | re.MULTILINE)
  330. if match:
  331. result = match.group(1)
  332. else:
  333. result = None
  334. try:
  335. if os.path.exists(result):
  336. with open(result) as namesFH:
  337. namesList = namesFH.read().strip().split("\n")
  338. altNames = [x.strip() for x in namesList]
  339. except TypeError:
  340. pass
  341. except Exception:
  342. pass
  343. if initOnly:
  344. print("Initialized detector")
  345. return None
  346. if not os.path.exists(imagePath):
  347. raise ValueError("Invalid image path `"+os.path.abspath(imagePath)+"`")
  348. # Do the detection
  349. #detections = detect(netMain, metaMain, imagePath, thresh) # if is used cv2.imread(image)
  350. detections = detect(netMain, metaMain, imagePath.encode("ascii"), thresh)
  351. data=[detections,imagePath]
  352. if showImage:
  353. try:
  354. from skimage import io, draw
  355. import numpy as np
  356. from PIL import Image
  357. image = io.imread(imagePath)
  358. print("*** "+str(len(detections))+" Results, color coded by confidence ***")
  359. imcaption = []
  360. for detection in detections:
  361. check=1
  362. label = detection[0]
  363. confidence = detection[1]
  364. pstring = label+": "+str(np.rint(100 * confidence))+"%"
  365. imcaption.append(pstring)
  366. print(pstring)
  367. bounds = detection[2]
  368. shape = image.shape
  369. # x = shape[1]
  370. # xExtent = int(x * bounds[2] / 100)
  371. # y = shape[0]
  372. # yExtent = int(y * bounds[3] / 100)
  373. yExtent = int(bounds[3])
  374. xEntent = int(bounds[2])
  375. print("-----------")
  376. for i in bounds:
  377. print(i)
  378. print("-----------")
  379. # Coordinates are around the center
  380. xCoord = int(bounds[0] - bounds[2]/2)
  381. yCoord = int(bounds[1] - bounds[3]/2)
  382. boundingBox = [
  383. [xCoord, yCoord],
  384. [xCoord, yCoord + yExtent],
  385. [xCoord + xEntent, yCoord + yExtent],
  386. [xCoord + xEntent, yCoord]
  387. ]
  388. topX=boundingBox[0][0]
  389. topY=boundingBox[0][1]
  390. botX=boundingBox[2][0]
  391. botY=boundingBox[2][1]
  392. bBoxCords = (topX,topY,botX,botY)
  393. data.append(bBoxCords)
  394. obj = Image.open(imagePath)
  395. obj = obj.crop(bBoxCords)
  396. obj.show()
  397. print(type(bBoxCords))
  398. # Wiggle it around to make a 3px border
  399. rr, cc = draw.polygon_perimeter([x[1] for x in boundingBox], [x[0] for x in boundingBox], shape= shape)
  400. rr2, cc2 = draw.polygon_perimeter([x[1] + 1 for x in boundingBox], [x[0] for x in boundingBox], shape= shape)
  401. rr3, cc3 = draw.polygon_perimeter([x[1] - 1 for x in boundingBox], [x[0] for x in boundingBox], shape= shape)
  402. rr4, cc4 = draw.polygon_perimeter([x[1] for x in boundingBox], [x[0] + 1 for x in boundingBox], shape= shape)
  403. rr5, cc5 = draw.polygon_perimeter([x[1] for x in boundingBox], [x[0] - 1 for x in boundingBox], shape= shape)
  404. boxColor = (int(255 * (1 - (confidence ** 2))), int(255 * (confidence ** 2)), 0)
  405. draw.set_color(image, (rr, cc), boxColor, alpha= 0.8)
  406. draw.set_color(image, (rr2, cc2), boxColor, alpha= 0.8)
  407. draw.set_color(image, (rr3, cc3), boxColor, alpha= 0.8)
  408. draw.set_color(image, (rr4, cc4), boxColor, alpha= 0.8)
  409. draw.set_color(image, (rr5, cc5), boxColor, alpha= 0.8)
  410.  
  411.  
  412. if not makeImageOnly:
  413. #F = Image.open(imagePath)
  414. #F.show()
  415. io.imshow(image)
  416. io.show()
  417. #F.crop(boundingBox)
  418. detections = {
  419. "detections": detections,
  420. "image": image,
  421. "caption": "\n<br/>".join(imcaption)
  422. }
  423. except Exception as e:
  424. print("Unable to show image: "+str(e))
  425. return data,check
  426.  
  427. #if __name__ == "__main__":
  428. # data,check = performDetect(imagePath="data/eagle.jpg")
  429. # print(data)
Add Comment
Please, Sign In to add comment