glenn-jocher
commited on
Commit
•
2da4e7a
1
Parent(s):
63e09fd
Merge PIL and OpenCV in `plot_one_box(use_pil=False)` (#4416)
Browse files* Merge PIL and OpenCV box plotting functions
* Add ASCII check to plot_one_box
* Cleanup
* Cleanup2
- detect.py +1 -1
- models/common.py +1 -1
- utils/general.py +6 -1
- utils/plots.py +27 -29
detect.py
CHANGED
@@ -156,7 +156,7 @@ def run(weights='yolov5s.pt', # model.pt path(s)
|
|
156 |
if save_img or save_crop or view_img: # Add bbox to image
|
157 |
c = int(cls) # integer class
|
158 |
label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
|
159 |
-
plot_one_box(xyxy, im0, label=label, color=colors(c, True),
|
160 |
if save_crop:
|
161 |
save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)
|
162 |
|
|
|
156 |
if save_img or save_crop or view_img: # Add bbox to image
|
157 |
c = int(cls) # integer class
|
158 |
label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
|
159 |
+
im0 = plot_one_box(xyxy, im0, label=label, color=colors(c, True), line_width=line_thickness)
|
160 |
if save_crop:
|
161 |
save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)
|
162 |
|
models/common.py
CHANGED
@@ -354,7 +354,7 @@ class Detections:
|
|
354 |
if crop:
|
355 |
save_one_box(box, im, file=save_dir / 'crops' / self.names[int(cls)] / self.files[i])
|
356 |
else: # all others
|
357 |
-
plot_one_box(box, im, label=label, color=colors(cls))
|
358 |
else:
|
359 |
str += '(no detections)'
|
360 |
|
|
|
354 |
if crop:
|
355 |
save_one_box(box, im, file=save_dir / 'crops' / self.names[int(cls)] / self.files[i])
|
356 |
else: # all others
|
357 |
+
im = plot_one_box(box, im, label=label, color=colors(cls))
|
358 |
else:
|
359 |
str += '(no detections)'
|
360 |
|
utils/general.py
CHANGED
@@ -110,9 +110,14 @@ def is_pip():
|
|
110 |
return 'site-packages' in Path(__file__).absolute().parts
|
111 |
|
112 |
|
|
|
|
|
|
|
|
|
|
|
113 |
def emojis(str=''):
|
114 |
# Return platform-dependent emoji-safe version of string
|
115 |
-
return str.encode().decode(
|
116 |
|
117 |
|
118 |
def file_size(file):
|
|
|
110 |
return 'site-packages' in Path(__file__).absolute().parts
|
111 |
|
112 |
|
113 |
+
def is_ascii(str=''):
|
114 |
+
# Is string composed of all ASCII (no UTF) characters?
|
115 |
+
return len(str.encode().decode('ascii', 'ignore')) == len(str)
|
116 |
+
|
117 |
+
|
118 |
def emojis(str=''):
|
119 |
# Return platform-dependent emoji-safe version of string
|
120 |
+
return str.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else str
|
121 |
|
122 |
|
123 |
def file_size(file):
|
utils/plots.py
CHANGED
@@ -1,20 +1,19 @@
|
|
1 |
# Plotting utils
|
2 |
|
|
|
3 |
from copy import copy
|
4 |
from pathlib import Path
|
5 |
|
6 |
import cv2
|
7 |
-
import math
|
8 |
import matplotlib
|
9 |
import matplotlib.pyplot as plt
|
10 |
import numpy as np
|
11 |
import pandas as pd
|
12 |
import seaborn as sn
|
13 |
import torch
|
14 |
-
import yaml
|
15 |
from PIL import Image, ImageDraw, ImageFont
|
16 |
|
17 |
-
from utils.general import
|
18 |
from utils.metrics import fitness
|
19 |
|
20 |
# Settings
|
@@ -65,32 +64,31 @@ def butter_lowpass_filtfilt(data, cutoff=1500, fs=50000, order=5):
|
|
65 |
return filtfilt(b, a, data) # forward-backward filter
|
66 |
|
67 |
|
68 |
-
def plot_one_box(
|
69 |
-
# Plots one
|
70 |
assert im.data.contiguous, 'Image not contiguous. Apply np.ascontiguousarray(im) to plot_on_box() input image.'
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
#
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
return np.asarray(im)
|
94 |
|
95 |
|
96 |
def plot_wh_methods(): # from utils.plots import *; plot_wh_methods()
|
@@ -180,7 +178,7 @@ def plot_images(images, targets, paths=None, fname='images.jpg', names=None, max
|
|
180 |
cls = names[cls] if names else cls
|
181 |
if labels or conf[j] > 0.25: # 0.25 conf thresh
|
182 |
label = '%s' % cls if labels else '%s %.1f' % (cls, conf[j])
|
183 |
-
plot_one_box(box, mosaic, label=label, color=color,
|
184 |
|
185 |
# Draw image filename labels
|
186 |
if paths:
|
|
|
1 |
# Plotting utils
|
2 |
|
3 |
+
import math
|
4 |
from copy import copy
|
5 |
from pathlib import Path
|
6 |
|
7 |
import cv2
|
|
|
8 |
import matplotlib
|
9 |
import matplotlib.pyplot as plt
|
10 |
import numpy as np
|
11 |
import pandas as pd
|
12 |
import seaborn as sn
|
13 |
import torch
|
|
|
14 |
from PIL import Image, ImageDraw, ImageFont
|
15 |
|
16 |
+
from utils.general import is_ascii, xyxy2xywh, xywh2xyxy
|
17 |
from utils.metrics import fitness
|
18 |
|
19 |
# Settings
|
|
|
64 |
return filtfilt(b, a, data) # forward-backward filter
|
65 |
|
66 |
|
67 |
+
def plot_one_box(box, im, color=(128, 128, 128), txt_color=(255, 255, 255), label=None, line_width=3, use_pil=False):
|
68 |
+
# Plots one xyxy box on image im with label
|
69 |
assert im.data.contiguous, 'Image not contiguous. Apply np.ascontiguousarray(im) to plot_on_box() input image.'
|
70 |
+
lw = line_width or max(int(min(im.size) / 200), 2) # line width
|
71 |
+
|
72 |
+
if use_pil or not is_ascii(label): # use PIL
|
73 |
+
im = Image.fromarray(im)
|
74 |
+
draw = ImageDraw.Draw(im)
|
75 |
+
draw.rectangle(box, width=lw + 1, outline=color) # plot
|
76 |
+
if label:
|
77 |
+
font = ImageFont.truetype("Arial.ttf", size=max(round(max(im.size) / 40), 12))
|
78 |
+
txt_width, txt_height = font.getsize(label)
|
79 |
+
draw.rectangle([box[0], box[1] - txt_height + 4, box[0] + txt_width, box[1]], fill=color)
|
80 |
+
draw.text((box[0], box[1] - txt_height + 1), label, fill=txt_color, font=font)
|
81 |
+
return np.asarray(im)
|
82 |
+
else: # use OpenCV
|
83 |
+
c1, c2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
|
84 |
+
cv2.rectangle(im, c1, c2, color, thickness=lw, lineType=cv2.LINE_AA)
|
85 |
+
if label:
|
86 |
+
tf = max(lw - 1, 1) # font thickness
|
87 |
+
txt_width, txt_height = cv2.getTextSize(label, 0, fontScale=lw / 3, thickness=tf)[0]
|
88 |
+
c2 = c1[0] + txt_width, c1[1] - txt_height - 3
|
89 |
+
cv2.rectangle(im, c1, c2, color, -1, cv2.LINE_AA) # filled
|
90 |
+
cv2.putText(im, label, (c1[0], c1[1] - 2), 0, lw / 3, txt_color, thickness=tf, lineType=cv2.LINE_AA)
|
91 |
+
return im
|
|
|
92 |
|
93 |
|
94 |
def plot_wh_methods(): # from utils.plots import *; plot_wh_methods()
|
|
|
178 |
cls = names[cls] if names else cls
|
179 |
if labels or conf[j] > 0.25: # 0.25 conf thresh
|
180 |
label = '%s' % cls if labels else '%s %.1f' % (cls, conf[j])
|
181 |
+
mosaic = plot_one_box(box, mosaic, label=label, color=color, line_width=tl)
|
182 |
|
183 |
# Draw image filename labels
|
184 |
if paths:
|