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.

576 lines
24KB

  1. # Plotting utils
  2. import glob
  3. import math
  4. import os
  5. import random
  6. from copy import copy
  7. from pathlib import Path
  8. import cv2
  9. import matplotlib
  10. import matplotlib.pyplot as plt
  11. import numpy as np
  12. import pandas as pd
  13. import seaborn as sns
  14. import torch
  15. import yaml
  16. from PIL import Image, ImageDraw, ImageFont
  17. from scipy.signal import butter, filtfilt,savgol_filter
  18. from utils.general import xywh2xyxy, xyxy2xywh
  19. from utils.metrics import fitness
  20. # Settings
  21. matplotlib.rc('font', **{'size': 11})
  22. #matplotlib.use('Agg') # for writing to files only
  23. def smooth_outline(contours,p1,p2):
  24. arcontours=np.array(contours)
  25. coors_x=arcontours[0,:,0,0]
  26. coors_y=arcontours[0,:,0,1]
  27. coors_x_smooth= savgol_filter(coors_x,p1,p2)
  28. coors_y_smooth= savgol_filter(coors_y,p1,p2)
  29. arcontours[0,:,0,0] = coors_x_smooth
  30. arcontours[0,:,0,1] = coors_y_smooth
  31. return arcontours
  32. def smooth_outline_auto(contours):
  33. cnt = len(contours[0])
  34. p1 = int(cnt/12)*2+1
  35. p2 =3
  36. if p1<p2: p2 = p1-1
  37. return smooth_outline(contours,p1,p2)
  38. def get_websource(txtfile):
  39. with open(txtfile,'r') as fp:
  40. lines = fp.readlines()
  41. webs=[];ports=[];streamNames=[]
  42. for line in lines:
  43. try:
  44. sps = line.strip().split(' ')
  45. webs.append(sps[0])
  46. #rtmp://liveplay.yunhengzhizao.cn/live/demo_HD5M
  47. if 'rtmp' in sps[0]:
  48. name = sps[0].split('/')[4].split('_')[0]
  49. else:
  50. name = sps[0][-3:]
  51. ports.append(sps[1])
  52. streamNames.append(name)
  53. except:
  54. print('####format error : %s , in file:%s#####'%(line,txtfile))
  55. assert len(webs)>0
  56. return webs,ports,streamNames
  57. def get_label_array( color=None, label=None,outfontsize=None):
  58. # Plots one bounding box on image 'im' using PIL
  59. fontsize = 48
  60. font = ImageFont.truetype("conf/platech.ttf", fontsize,encoding='utf-8')
  61. txt_width, txt_height = font.getsize(label)
  62. im = np.zeros((txt_height,txt_width,3),dtype=np.uint8)
  63. im = Image.fromarray(im)
  64. draw = ImageDraw.Draw(im)
  65. draw.rectangle([0, 0 , txt_width, txt_height ], fill=tuple(color))
  66. draw.text(( 0 , -3 ), label, fill=(255, 255, 255), font=font)
  67. im_array = np.asarray(im)
  68. if outfontsize:
  69. scaley = outfontsize / txt_height
  70. im_array= cv2.resize(im_array,(0,0),fx = scaley ,fy =scaley)
  71. return im_array
  72. def get_label_arrays(labelnames,colors,outfontsize=40):
  73. label_arraylist = []
  74. if len(labelnames) > len(colors):
  75. print('#####labelnames cnt > colors cnt#####')
  76. for ii,labelname in enumerate(labelnames):
  77. color = colors[ii%20]
  78. label_arraylist.append(get_label_array(color=color,label=labelname,outfontsize=40))
  79. return label_arraylist
  80. def color_list():
  81. # Return first 10 plt colors as (r,g,b) https://stackoverflow.com/questions/51350872/python-from-color-name-to-rgb
  82. def hex2rgb(h):
  83. return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
  84. return [hex2rgb(h) for h in matplotlib.colors.TABLEAU_COLORS.values()] # or BASE_ (8), CSS4_ (148), XKCD_ (949)
  85. def hist2d(x, y, n=100):
  86. # 2d histogram used in labels.png and evolve.png
  87. xedges, yedges = np.linspace(x.min(), x.max(), n), np.linspace(y.min(), y.max(), n)
  88. hist, xedges, yedges = np.histogram2d(x, y, (xedges, yedges))
  89. xidx = np.clip(np.digitize(x, xedges) - 1, 0, hist.shape[0] - 1)
  90. yidx = np.clip(np.digitize(y, yedges) - 1, 0, hist.shape[1] - 1)
  91. return np.log(hist[xidx, yidx])
  92. def butter_lowpass_filtfilt(data, cutoff=1500, fs=50000, order=5):
  93. # https://stackoverflow.com/questions/28536191/how-to-filter-smooth-with-scipy-numpy
  94. def butter_lowpass(cutoff, fs, order):
  95. nyq = 0.5 * fs
  96. normal_cutoff = cutoff / nyq
  97. return butter(order, normal_cutoff, btype='low', analog=False)
  98. b, a = butter_lowpass(cutoff, fs, order=order)
  99. return filtfilt(b, a, data) # forward-backward filter
  100. '''image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  101. pil_image = Image.fromarray(image)
  102. draw = ImageDraw.Draw(pil_image)
  103. font = ImageFont.truetype('./font/platech.ttf', 40, encoding='utf-8')
  104. for info in infos:
  105. detect = info['bndbox']
  106. text = ','.join(list(info['attributes'].values()))
  107. temp = -50
  108. if info['name'] == 'vehicle':
  109. temp = 20
  110. draw.text((detect[0], detect[1] + temp), text, (0, 255, 255), font=font)
  111. if 'scores' in info:
  112. draw.text((detect[0], detect[3]), info['scores'], (0, 255, 0), font=font)
  113. if 'pscore' in info:
  114. draw.text((detect[2], detect[3]), str(round(info['pscore'],3)), (0, 255, 0), font=font)
  115. image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
  116. for info in infos:
  117. detect = info['bndbox']
  118. cv2.rectangle(image, (detect[0], detect[1]), (detect[2], detect[3]), (0, 255, 0), 1, cv2.LINE_AA)
  119. return image'''
  120. '''def plot_one_box_PIL(x, im, color=None, label=None, line_thickness=3):
  121. # Plots one bounding box on image 'im' using OpenCV
  122. assert im.data.contiguous, 'Image not contiguous. Apply np.ascontiguousarray(im) to plot_on_box() input image.'
  123. tl = line_thickness or round(0.002 * (im.shape[0] + im.shape[1]) / 2) + 1 # line/font thickness
  124. color = color or [random.randint(0, 255) for _ in range(3)]
  125. c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
  126. cv2.rectangle(im, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
  127. if label:
  128. tf = max(tl - 1, 1) # font thickness
  129. t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
  130. c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
  131. cv2.rectangle(im, c1, c2, color, -1, cv2.LINE_AA) # filled
  132. im = Image.fromarray(im)
  133. draw = ImageDraw.Draw(im)
  134. font = ImageFont.truetype('./font/platech.ttf', t_size, encoding='utf-8')
  135. draw.text((c1[0], c1[1] - 2), label, (0, 255, 0), font=font)
  136. #cv2.putText(im, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  137. return np.array(im) '''
  138. def plot_one_box(x, im, color=None, label=None, line_thickness=3):
  139. # Plots one bounding box on image 'im' using OpenCV
  140. assert im.data.contiguous, 'Image not contiguous. Apply np.ascontiguousarray(im) to plot_on_box() input image.'
  141. tl = line_thickness or round(0.002 * (im.shape[0] + im.shape[1]) / 2) + 1 # line/font thickness
  142. color = color or [random.randint(0, 255) for _ in range(3)]
  143. c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
  144. cv2.rectangle(im, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
  145. if label:
  146. tf = max(tl - 1, 1) # font thickness
  147. t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
  148. c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
  149. cv2.rectangle(im, c1, c2, color, -1, cv2.LINE_AA) # filled
  150. cv2.putText(im, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  151. def plot_one_box_PIL(box, im, color=None, label=None, line_thickness=None):
  152. # Plots one bounding box on image 'im' using PIL
  153. print('##line149:',box)
  154. im = Image.fromarray(im)
  155. draw = ImageDraw.Draw(im)
  156. line_thickness = line_thickness or max(int(min(im.size) / 200), 2)
  157. draw.rectangle(box, width=line_thickness, outline=tuple(color)) # plot
  158. if label:
  159. fontsize = max(round(max(im.size) / 40), 12)
  160. font = ImageFont.truetype("platech.ttf", fontsize,encoding='utf-8')
  161. txt_width, txt_height = font.getsize(label)
  162. draw.rectangle([box[0], box[1] - txt_height + 4, box[0] + txt_width, box[1]], fill=tuple(color))
  163. draw.text((box[0], box[1] - txt_height + 1), label, fill=(255, 255, 255), font=font)
  164. im_array = np.asarray(im)
  165. return np.asarray(im)
  166. def draw_painting_joint(box,img,label_array,score=0.5,color=None,line_thickness=None):
  167. box = [int(xx.cpu()) for xx in box]
  168. lh, lw, lc = label_array.shape
  169. imh, imw, imc = img.shape
  170. x0 , y1 = box[0:2]
  171. x1 , y0 = x0 + lw , y1 - lh
  172. y0 = max(0,y0) ; y1 = y0 + lh
  173. x1 = min(imw, x1); x0 = x1 - lw
  174. img[y0:y1,x0:x1,:] = label_array
  175. tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
  176. c1, c2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
  177. cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
  178. label = ' %.2f'%(score)
  179. tf = max(tl - 1, 1) # font thickness
  180. fontScale = tl * 0.33
  181. t_size = cv2.getTextSize(label, 0, fontScale=fontScale , thickness=tf)[0]
  182. c2 = c1[0]+ lw + t_size[0], c1[1] - lh
  183. cv2.rectangle(img, (int(box[0])+lw,int(box[1])) , c2, color, -1, cv2.LINE_AA) # filled
  184. cv2.putText(img, label, (c1[0]+lw, c1[1] - (lh-t_size[1])//2 ), 0, fontScale, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  185. return img
  186. def plot_wh_methods(): # from utils.plots import *; plot_wh_methods()
  187. # Compares the two methods for width-height anchor multiplication
  188. # https://github.com/ultralytics/yolov3/issues/168
  189. x = np.arange(-4.0, 4.0, .1)
  190. ya = np.exp(x)
  191. yb = torch.sigmoid(torch.from_numpy(x)).numpy() * 2
  192. fig = plt.figure(figsize=(6, 3), tight_layout=True)
  193. plt.plot(x, ya, '.-', label='YOLOv3')
  194. plt.plot(x, yb ** 2, '.-', label='YOLOv5 ^2')
  195. plt.plot(x, yb ** 1.6, '.-', label='YOLOv5 ^1.6')
  196. plt.xlim(left=-4, right=4)
  197. plt.ylim(bottom=0, top=6)
  198. plt.xlabel('input')
  199. plt.ylabel('output')
  200. plt.grid()
  201. plt.legend()
  202. fig.savefig('comparison.png', dpi=200)
  203. def output_to_target(output):
  204. # Convert model output to target format [batch_id, class_id, x, y, w, h, conf]
  205. targets = []
  206. for i, o in enumerate(output):
  207. for *box, conf, cls in o.cpu().numpy():
  208. targets.append([i, cls, *list(*xyxy2xywh(np.array(box)[None])), conf])
  209. return np.array(targets)
  210. def plot_images(images, targets, paths=None, fname='images.jpg', names=None, max_size=640, max_subplots=16):
  211. # Plot image grid with labels
  212. if isinstance(images, torch.Tensor):
  213. images = images.cpu().float().numpy()
  214. if isinstance(targets, torch.Tensor):
  215. targets = targets.cpu().numpy()
  216. # un-normalise
  217. if np.max(images[0]) <= 1:
  218. images *= 255
  219. tl = 3 # line thickness
  220. tf = max(tl - 1, 1) # font thickness
  221. bs, _, h, w = images.shape # batch size, _, height, width
  222. bs = min(bs, max_subplots) # limit plot images
  223. ns = np.ceil(bs ** 0.5) # number of subplots (square)
  224. # Check if we should resize
  225. scale_factor = max_size / max(h, w)
  226. if scale_factor < 1:
  227. h = math.ceil(scale_factor * h)
  228. w = math.ceil(scale_factor * w)
  229. colors = color_list() # list of colors
  230. mosaic = np.full((int(ns * h), int(ns * w), 3), 255, dtype=np.uint8) # init
  231. for i, img in enumerate(images):
  232. if i == max_subplots: # if last batch has fewer images than we expect
  233. break
  234. block_x = int(w * (i // ns))
  235. block_y = int(h * (i % ns))
  236. img = img.transpose(1, 2, 0)
  237. if scale_factor < 1:
  238. img = cv2.resize(img, (w, h))
  239. mosaic[block_y:block_y + h, block_x:block_x + w, :] = img
  240. if len(targets) > 0:
  241. image_targets = targets[targets[:, 0] == i]
  242. boxes = xywh2xyxy(image_targets[:, 2:6]).T
  243. classes = image_targets[:, 1].astype('int')
  244. labels = image_targets.shape[1] == 6 # labels if no conf column
  245. conf = None if labels else image_targets[:, 6] # check for confidence presence (label vs pred)
  246. if boxes.shape[1]:
  247. if boxes.max() <= 1.01: # if normalized with tolerance 0.01
  248. boxes[[0, 2]] *= w # scale to pixels
  249. boxes[[1, 3]] *= h
  250. elif scale_factor < 1: # absolute coords need scale if image scales
  251. boxes *= scale_factor
  252. boxes[[0, 2]] += block_x
  253. boxes[[1, 3]] += block_y
  254. for j, box in enumerate(boxes.T):
  255. cls = int(classes[j])
  256. color = colors[cls % len(colors)]
  257. cls = names[cls] if names else cls
  258. if labels or conf[j] > 0.25: # 0.25 conf thresh
  259. label = '%s' % cls if labels else '%s %.1f' % (cls, conf[j])
  260. plot_one_box(box, mosaic, label=label, color=color, line_thickness=tl)
  261. # Draw image filename labels
  262. if paths:
  263. label = Path(paths[i]).name[:40] # trim to 40 char
  264. t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
  265. cv2.putText(mosaic, label, (block_x + 5, block_y + t_size[1] + 5), 0, tl / 3, [220, 220, 220], thickness=tf,
  266. lineType=cv2.LINE_AA)
  267. # Image border
  268. cv2.rectangle(mosaic, (block_x, block_y), (block_x + w, block_y + h), (255, 255, 255), thickness=3)
  269. if fname:
  270. r = min(1280. / max(h, w) / ns, 1.0) # ratio to limit image size
  271. mosaic = cv2.resize(mosaic, (int(ns * w * r), int(ns * h * r)), interpolation=cv2.INTER_AREA)
  272. # cv2.imwrite(fname, cv2.cvtColor(mosaic, cv2.COLOR_BGR2RGB)) # cv2 save
  273. Image.fromarray(mosaic).save(fname) # PIL save
  274. return mosaic
  275. def plot_lr_scheduler(optimizer, scheduler, epochs=300, save_dir=''):
  276. # Plot LR simulating training for full epochs
  277. optimizer, scheduler = copy(optimizer), copy(scheduler) # do not modify originals
  278. y = []
  279. for _ in range(epochs):
  280. scheduler.step()
  281. y.append(optimizer.param_groups[0]['lr'])
  282. plt.plot(y, '.-', label='LR')
  283. plt.xlabel('epoch')
  284. plt.ylabel('LR')
  285. plt.grid()
  286. plt.xlim(0, epochs)
  287. plt.ylim(0)
  288. plt.savefig(Path(save_dir) / 'LR.png', dpi=200)
  289. plt.close()
  290. def plot_test_txt(): # from utils.plots import *; plot_test()
  291. # Plot test.txt histograms
  292. x = np.loadtxt('test.txt', dtype=np.float32)
  293. box = xyxy2xywh(x[:, :4])
  294. cx, cy = box[:, 0], box[:, 1]
  295. fig, ax = plt.subplots(1, 1, figsize=(6, 6), tight_layout=True)
  296. ax.hist2d(cx, cy, bins=600, cmax=10, cmin=0)
  297. ax.set_aspect('equal')
  298. plt.savefig('hist2d.png', dpi=300)
  299. fig, ax = plt.subplots(1, 2, figsize=(12, 6), tight_layout=True)
  300. ax[0].hist(cx, bins=600)
  301. ax[1].hist(cy, bins=600)
  302. plt.savefig('hist1d.png', dpi=200)
  303. def plot_targets_txt(): # from utils.plots import *; plot_targets_txt()
  304. # Plot targets.txt histograms
  305. x = np.loadtxt('targets.txt', dtype=np.float32).T
  306. s = ['x targets', 'y targets', 'width targets', 'height targets']
  307. fig, ax = plt.subplots(2, 2, figsize=(8, 8), tight_layout=True)
  308. ax = ax.ravel()
  309. for i in range(4):
  310. ax[i].hist(x[i], bins=100, label='%.3g +/- %.3g' % (x[i].mean(), x[i].std()))
  311. ax[i].legend()
  312. ax[i].set_title(s[i])
  313. plt.savefig('targets.jpg', dpi=200)
  314. def plot_study_txt(path='', x=None): # from utils.plots import *; plot_study_txt()
  315. # Plot study.txt generated by test.py
  316. fig, ax = plt.subplots(2, 4, figsize=(10, 6), tight_layout=True)
  317. # ax = ax.ravel()
  318. fig2, ax2 = plt.subplots(1, 1, figsize=(8, 4), tight_layout=True)
  319. # for f in [Path(path) / f'study_coco_{x}.txt' for x in ['yolov5s6', 'yolov5m6', 'yolov5l6', 'yolov5x6']]:
  320. for f in sorted(Path(path).glob('study*.txt')):
  321. y = np.loadtxt(f, dtype=np.float32, usecols=[0, 1, 2, 3, 7, 8, 9], ndmin=2).T
  322. x = np.arange(y.shape[1]) if x is None else np.array(x)
  323. s = ['P', 'R', 'mAP@.5', 'mAP@.5:.95', 't_inference (ms/img)', 't_NMS (ms/img)', 't_total (ms/img)']
  324. # for i in range(7):
  325. # ax[i].plot(x, y[i], '.-', linewidth=2, markersize=8)
  326. # ax[i].set_title(s[i])
  327. j = y[3].argmax() + 1
  328. ax2.plot(y[6, 1:j], y[3, 1:j] * 1E2, '.-', linewidth=2, markersize=8,
  329. label=f.stem.replace('study_coco_', '').replace('yolo', 'YOLO'))
  330. ax2.plot(1E3 / np.array([209, 140, 97, 58, 35, 18]), [34.6, 40.5, 43.0, 47.5, 49.7, 51.5],
  331. 'k.-', linewidth=2, markersize=8, alpha=.25, label='EfficientDet')
  332. ax2.grid(alpha=0.2)
  333. ax2.set_yticks(np.arange(20, 60, 5))
  334. ax2.set_xlim(0, 57)
  335. ax2.set_ylim(30, 55)
  336. ax2.set_xlabel('GPU Speed (ms/img)')
  337. ax2.set_ylabel('COCO AP val')
  338. ax2.legend(loc='lower right')
  339. plt.savefig(str(Path(path).name) + '.png', dpi=300)
  340. def plot_labels(labels, names=(), save_dir=Path(''), loggers=None):
  341. # plot dataset labels
  342. print('Plotting labels... ')
  343. c, b = labels[:, 0], labels[:, 1:].transpose() # classes, boxes
  344. nc = int(c.max() + 1) # number of classes
  345. colors = color_list()
  346. x = pd.DataFrame(b.transpose(), columns=['x', 'y', 'width', 'height'])
  347. # seaborn correlogram
  348. sns.pairplot(x, corner=True, diag_kind='auto', kind='hist', diag_kws=dict(bins=50), plot_kws=dict(pmax=0.9))
  349. plt.savefig(save_dir / 'labels_correlogram.jpg', dpi=200)
  350. plt.close()
  351. # matplotlib labels
  352. matplotlib.use('svg') # faster
  353. ax = plt.subplots(2, 2, figsize=(8, 8), tight_layout=True)[1].ravel()
  354. ax[0].hist(c, bins=np.linspace(0, nc, nc + 1) - 0.5, rwidth=0.8)
  355. ax[0].set_ylabel('instances')
  356. if 0 < len(names) < 30:
  357. ax[0].set_xticks(range(len(names)))
  358. ax[0].set_xticklabels(names, rotation=90, fontsize=10)
  359. else:
  360. ax[0].set_xlabel('classes')
  361. sns.histplot(x, x='x', y='y', ax=ax[2], bins=50, pmax=0.9)
  362. sns.histplot(x, x='width', y='height', ax=ax[3], bins=50, pmax=0.9)
  363. # rectangles
  364. labels[:, 1:3] = 0.5 # center
  365. labels[:, 1:] = xywh2xyxy(labels[:, 1:]) * 2000
  366. img = Image.fromarray(np.ones((2000, 2000, 3), dtype=np.uint8) * 255)
  367. for cls, *box in labels[:1000]:
  368. ImageDraw.Draw(img).rectangle(box, width=1, outline=colors[int(cls) % 10]) # plot
  369. ax[1].imshow(img)
  370. ax[1].axis('off')
  371. for a in [0, 1, 2, 3]:
  372. for s in ['top', 'right', 'left', 'bottom']:
  373. ax[a].spines[s].set_visible(False)
  374. plt.savefig(save_dir / 'labels.jpg', dpi=200)
  375. matplotlib.use('Agg')
  376. plt.close()
  377. # loggers
  378. for k, v in loggers.items() or {}:
  379. if k == 'wandb' and v:
  380. v.log({"Labels": [v.Image(str(x), caption=x.name) for x in save_dir.glob('*labels*.jpg')]}, commit=False)
  381. def plot_evolution(yaml_file='data/hyp.finetune.yaml'): # from utils.plots import *; plot_evolution()
  382. # Plot hyperparameter evolution results in evolve.txt
  383. with open(yaml_file) as f:
  384. hyp = yaml.load(f, Loader=yaml.SafeLoader)
  385. x = np.loadtxt('evolve.txt', ndmin=2)
  386. f = fitness(x)
  387. # weights = (f - f.min()) ** 2 # for weighted results
  388. plt.figure(figsize=(10, 12), tight_layout=True)
  389. matplotlib.rc('font', **{'size': 8})
  390. for i, (k, v) in enumerate(hyp.items()):
  391. y = x[:, i + 7]
  392. # mu = (y * weights).sum() / weights.sum() # best weighted result
  393. mu = y[f.argmax()] # best single result
  394. plt.subplot(6, 5, i + 1)
  395. plt.scatter(y, f, c=hist2d(y, f, 20), cmap='viridis', alpha=.8, edgecolors='none')
  396. plt.plot(mu, f.max(), 'k+', markersize=15)
  397. plt.title('%s = %.3g' % (k, mu), fontdict={'size': 9}) # limit to 40 characters
  398. if i % 5 != 0:
  399. plt.yticks([])
  400. print('%15s: %.3g' % (k, mu))
  401. plt.savefig('evolve.png', dpi=200)
  402. print('\nPlot saved as evolve.png')
  403. def profile_idetection(start=0, stop=0, labels=(), save_dir=''):
  404. # Plot iDetection '*.txt' per-image logs. from utils.plots import *; profile_idetection()
  405. ax = plt.subplots(2, 4, figsize=(12, 6), tight_layout=True)[1].ravel()
  406. s = ['Images', 'Free Storage (GB)', 'RAM Usage (GB)', 'Battery', 'dt_raw (ms)', 'dt_smooth (ms)', 'real-world FPS']
  407. files = list(Path(save_dir).glob('frames*.txt'))
  408. for fi, f in enumerate(files):
  409. try:
  410. results = np.loadtxt(f, ndmin=2).T[:, 90:-30] # clip first and last rows
  411. n = results.shape[1] # number of rows
  412. x = np.arange(start, min(stop, n) if stop else n)
  413. results = results[:, x]
  414. t = (results[0] - results[0].min()) # set t0=0s
  415. results[0] = x
  416. for i, a in enumerate(ax):
  417. if i < len(results):
  418. label = labels[fi] if len(labels) else f.stem.replace('frames_', '')
  419. a.plot(t, results[i], marker='.', label=label, linewidth=1, markersize=5)
  420. a.set_title(s[i])
  421. a.set_xlabel('time (s)')
  422. # if fi == len(files) - 1:
  423. # a.set_ylim(bottom=0)
  424. for side in ['top', 'right']:
  425. a.spines[side].set_visible(False)
  426. else:
  427. a.remove()
  428. except Exception as e:
  429. print('Warning: Plotting error for %s; %s' % (f, e))
  430. ax[1].legend()
  431. plt.savefig(Path(save_dir) / 'idetection_profile.png', dpi=200)
  432. def plot_results_overlay(start=0, stop=0): # from utils.plots import *; plot_results_overlay()
  433. # Plot training 'results*.txt', overlaying train and val losses
  434. s = ['train', 'train', 'train', 'Precision', 'mAP@0.5', 'val', 'val', 'val', 'Recall', 'mAP@0.5:0.95'] # legends
  435. t = ['Box', 'Objectness', 'Classification', 'P-R', 'mAP-F1'] # titles
  436. for f in sorted(glob.glob('results*.txt') + glob.glob('../../Downloads/results*.txt')):
  437. results = np.loadtxt(f, usecols=[2, 3, 4, 8, 9, 12, 13, 14, 10, 11], ndmin=2).T
  438. n = results.shape[1] # number of rows
  439. x = range(start, min(stop, n) if stop else n)
  440. fig, ax = plt.subplots(1, 5, figsize=(14, 3.5), tight_layout=True)
  441. ax = ax.ravel()
  442. for i in range(5):
  443. for j in [i, i + 5]:
  444. y = results[j, x]
  445. ax[i].plot(x, y, marker='.', label=s[j])
  446. # y_smooth = butter_lowpass_filtfilt(y)
  447. # ax[i].plot(x, np.gradient(y_smooth), marker='.', label=s[j])
  448. ax[i].set_title(t[i])
  449. ax[i].legend()
  450. ax[i].set_ylabel(f) if i == 0 else None # add filename
  451. fig.savefig(f.replace('.txt', '.png'), dpi=200)
  452. def plot_results(start=0, stop=0, bucket='', id=(), labels=(), save_dir=''):
  453. # Plot training 'results*.txt'. from utils.plots import *; plot_results(save_dir='runs/train/exp')
  454. fig, ax = plt.subplots(2, 5, figsize=(12, 6), tight_layout=True)
  455. ax = ax.ravel()
  456. s = ['Box', 'Objectness', 'Classification', 'Precision', 'Recall',
  457. 'val Box', 'val Objectness', 'val Classification', 'mAP@0.5', 'mAP@0.5:0.95']
  458. if bucket:
  459. # files = ['https://storage.googleapis.com/%s/results%g.txt' % (bucket, x) for x in id]
  460. files = ['results%g.txt' % x for x in id]
  461. c = ('gsutil cp ' + '%s ' * len(files) + '.') % tuple('gs://%s/results%g.txt' % (bucket, x) for x in id)
  462. os.system(c)
  463. else:
  464. files = list(Path(save_dir).glob('results*.txt'))
  465. assert len(files), 'No results.txt files found in %s, nothing to plot.' % os.path.abspath(save_dir)
  466. for fi, f in enumerate(files):
  467. try:
  468. results = np.loadtxt(f, usecols=[2, 3, 4, 8, 9, 12, 13, 14, 10, 11], ndmin=2).T
  469. n = results.shape[1] # number of rows
  470. x = range(start, min(stop, n) if stop else n)
  471. for i in range(10):
  472. y = results[i, x]
  473. if i in [0, 1, 2, 5, 6, 7]:
  474. y[y == 0] = np.nan # don't show zero loss values
  475. # y /= y[0] # normalize
  476. label = labels[fi] if len(labels) else f.stem
  477. ax[i].plot(x, y, marker='.', label=label, linewidth=2, markersize=8)
  478. ax[i].set_title(s[i])
  479. # if i in [5, 6, 7]: # share train and val loss y axes
  480. # ax[i].get_shared_y_axes().join(ax[i], ax[i - 5])
  481. except Exception as e:
  482. print('Warning: Plotting error for %s; %s' % (f, e))
  483. ax[1].legend()
  484. fig.savefig(Path(save_dir) / 'results.png', dpi=200)