Spaces:
Build error
Build error
onipot
commited on
Commit
•
bd1ea7f
1
Parent(s):
0fe9ba3
pil image as input
Browse files- app.py +30 -31
- yolov5/detect.py +39 -256
- yolov5/utils/datasets.py +13 -0
app.py
CHANGED
@@ -5,11 +5,12 @@ import torch
|
|
5 |
from util import Detection
|
6 |
import os
|
7 |
|
8 |
-
|
9 |
-
|
|
|
10 |
|
11 |
-
torch.hub.download_url_to_file(face_model, 'face_model.pt')
|
12 |
-
torch.hub.download_url_to_file(age_model, 'age_model.pt')
|
13 |
|
14 |
sys.path.append("./")
|
15 |
sys.path.append("./yolov5")
|
@@ -29,41 +30,39 @@ def run_yolo(img):
|
|
29 |
|
30 |
img0 = ImageOps.contain(img0, (720,720))
|
31 |
img0 = ImageOps.exif_transpose(img0)
|
32 |
-
|
33 |
-
img0.save("img.jpg")
|
34 |
|
35 |
draw = ImageDraw.Draw(img0)
|
36 |
|
37 |
-
predictions = predict(age_model_ts, model,
|
38 |
-
|
|
|
|
|
|
|
39 |
|
40 |
detections : list[Detection] = []
|
41 |
-
for k,
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
draw.rectangle(((det.xmin, det.ymin), (det.xmax, det.ymax)), fill=None, outline=(255,255,255))
|
60 |
-
draw.rectangle(((det.xmin, det.ymin - 10), (det.xmax, det.ymin)), fill=(255,255,255))
|
61 |
-
draw.text((det.xmin, det.ymin - 10), det.class_name, fill=(0,0,0), font=roboto_font)
|
62 |
-
|
63 |
-
os.remove("img.jpg")
|
64 |
return img0
|
65 |
|
66 |
|
|
|
|
|
67 |
inputs = gr.inputs.Image(type='filepath', label="Input Image")
|
68 |
outputs = gr.outputs.Image(type="pil", label="Output Image")
|
69 |
|
|
|
5 |
from util import Detection
|
6 |
import os
|
7 |
|
8 |
+
if os.environ.get('FACE_MODEL') is not None:
|
9 |
+
face_model = os.environ.get('FACE_MODEL')
|
10 |
+
age_model = os.environ.get('AGE_MODEL')
|
11 |
|
12 |
+
torch.hub.download_url_to_file(face_model, 'face_model.pt')
|
13 |
+
torch.hub.download_url_to_file(age_model, 'age_model.pt')
|
14 |
|
15 |
sys.path.append("./")
|
16 |
sys.path.append("./yolov5")
|
|
|
30 |
|
31 |
img0 = ImageOps.contain(img0, (720,720))
|
32 |
img0 = ImageOps.exif_transpose(img0)
|
|
|
|
|
33 |
|
34 |
draw = ImageDraw.Draw(img0)
|
35 |
|
36 |
+
predictions = predict(age_model_ts, model,
|
37 |
+
stride, imgsz=[320, 320],
|
38 |
+
conf_thres=0.5, iou_thres=0.45,
|
39 |
+
source=img0
|
40 |
+
)
|
41 |
|
42 |
detections : list[Detection] = []
|
43 |
+
for k, bbox in enumerate(predictions):
|
44 |
+
det = Detection(
|
45 |
+
(k+1),
|
46 |
+
bbox["xmin"],
|
47 |
+
bbox["ymin"],
|
48 |
+
bbox["xmax"],
|
49 |
+
bbox["ymax"],
|
50 |
+
bbox["conf"],
|
51 |
+
bbox["class"],
|
52 |
+
bbox["class"],
|
53 |
+
img0.size
|
54 |
+
)
|
55 |
+
|
56 |
+
detections.append(det)
|
57 |
+
draw.rectangle(((det.xmin, det.ymin), (det.xmax, det.ymax)), fill=None, outline=(255,255,255))
|
58 |
+
draw.rectangle(((det.xmin, det.ymin - 10), (det.xmax, det.ymin)), fill=(255,255,255))
|
59 |
+
draw.text((det.xmin, det.ymin - 10), det.class_name, fill=(0,0,0), font=roboto_font)
|
60 |
+
|
|
|
|
|
|
|
|
|
|
|
61 |
return img0
|
62 |
|
63 |
|
64 |
+
# run_yolo("D:\\Download\\IMG_20220803_153335.jpg")
|
65 |
+
|
66 |
inputs = gr.inputs.Image(type='filepath', label="Input Image")
|
67 |
outputs = gr.outputs.Image(type="pil", label="Output Image")
|
68 |
|
yolov5/detect.py
CHANGED
@@ -18,7 +18,7 @@ from yolov5.utils.torch_utils import select_device, time_sync
|
|
18 |
from yolov5.utils.plots import Annotator, colors, save_one_box
|
19 |
from yolov5.utils.general import (check_img_size,
|
20 |
increment_path, non_max_suppression, scale_coords, xyxy2xywh)
|
21 |
-
from yolov5.utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages
|
22 |
from yolov5.models.common import DetectMultiBackend
|
23 |
import torchvision
|
24 |
|
@@ -29,188 +29,6 @@ test_transforms = torchvision.transforms.Compose([
|
|
29 |
torchvision.transforms.Resize((224, 224)),
|
30 |
])
|
31 |
|
32 |
-
def run(weights=ROOT / 'yolov5s.pt', # model.pt path(s)
|
33 |
-
source=ROOT / 'data/images', # file/dir/URL/glob, 0 for webcam
|
34 |
-
data=ROOT / 'data/coco128.yaml', # dataset.yaml path
|
35 |
-
imgsz=(640, 640), # inference size (height, width)
|
36 |
-
conf_thres=0.25, # confidence threshold
|
37 |
-
iou_thres=0.45, # NMS IOU threshold
|
38 |
-
max_det=1000, # maximum detections per image
|
39 |
-
device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
|
40 |
-
save_img = False,
|
41 |
-
view_img=False, # show results
|
42 |
-
save_txt=False, # save results to *.txt
|
43 |
-
save_conf=False, # save confidences in --save-txt labels
|
44 |
-
save_crop=False, # save cropped prediction boxes
|
45 |
-
nosave=False, # do not save images/videos
|
46 |
-
classes=None, # filter by class: --class 0, or --class 0 2 3
|
47 |
-
agnostic_nms=False, # class-agnostic NMS
|
48 |
-
augment=False, # augmented inference
|
49 |
-
visualize=False, # visualize features
|
50 |
-
update=False, # update all models
|
51 |
-
project=ROOT / 'runs/detect', # save results to project/name
|
52 |
-
name='exp', # save results to project/name
|
53 |
-
exist_ok=False, # existing project/name ok, do not increment
|
54 |
-
line_thickness=3, # bounding box thickness (pixels)
|
55 |
-
hide_labels=False, # hide labels
|
56 |
-
hide_conf=False, # hide confidences
|
57 |
-
half=False, # use FP16 half-precision inference
|
58 |
-
dnn=False, # use OpenCV DNN for ONNX inference
|
59 |
-
):
|
60 |
-
|
61 |
-
import torch
|
62 |
-
from utils.torch_utils import select_device, time_sync
|
63 |
-
from utils.plots import Annotator, colors, save_one_box
|
64 |
-
from utils.general import (check_img_size,
|
65 |
-
increment_path, non_max_suppression, scale_coords, xyxy2xywh)
|
66 |
-
from utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages
|
67 |
-
from models.common import DetectMultiBackend
|
68 |
-
source = str(source)
|
69 |
-
|
70 |
-
save_dir = None
|
71 |
-
save_path = None
|
72 |
-
# save_img = not nosave and not source.endswith('.txt') # save inference images
|
73 |
-
is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
|
74 |
-
is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))
|
75 |
-
webcam = source.isnumeric() or source.endswith('.txt') or (is_url and not is_file)
|
76 |
-
|
77 |
-
# Directories
|
78 |
-
if project is not None:
|
79 |
-
save_dir = increment_path(Path(project) / name, exist_ok=exist_ok) # increment run
|
80 |
-
(save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True) # make dir
|
81 |
-
|
82 |
-
# Load model
|
83 |
-
device = select_device(device)
|
84 |
-
model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data)
|
85 |
-
stride, names, pt, jit, onnx, engine = model.stride, model.names, model.pt, model.jit, model.onnx, model.engine
|
86 |
-
imgsz = check_img_size(imgsz, s=stride) # check image size
|
87 |
-
|
88 |
-
# Half
|
89 |
-
half &= (pt or jit or onnx or engine) and device.type != 'cpu' # FP16 supported on limited backends with CUDA
|
90 |
-
if pt or jit:
|
91 |
-
model.model.half() if half else model.model.float()
|
92 |
-
|
93 |
-
dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt)
|
94 |
-
bs = 1 # batch_size
|
95 |
-
vid_path, vid_writer = [None] * bs, [None] * bs
|
96 |
-
|
97 |
-
# Run inference
|
98 |
-
model.warmup(imgsz=(1, 3, *imgsz), half=half) # warmup
|
99 |
-
dt, seen = [0.0, 0.0, 0.0], 0
|
100 |
-
|
101 |
-
#with tqdm(dataset) as pbar:
|
102 |
-
# pbar.set_description("Document Image Analysis")
|
103 |
-
for path, im, im0s, vid_cap, s in dataset:
|
104 |
-
#print(path)
|
105 |
-
t1 = time_sync()
|
106 |
-
im = torch.from_numpy(im).to(device)
|
107 |
-
im = im.half() if half else im.float() # uint8 to fp16/32
|
108 |
-
im /= 255 # 0 - 255 to 0.0 - 1.0
|
109 |
-
if len(im.shape) == 3:
|
110 |
-
im = im[None] # expand for batch dim
|
111 |
-
t2 = time_sync()
|
112 |
-
dt[0] += t2 - t1
|
113 |
-
|
114 |
-
# Inference
|
115 |
-
visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
|
116 |
-
pred = model(im, augment=augment, visualize=visualize)
|
117 |
-
t3 = time_sync()
|
118 |
-
dt[1] += t3 - t2
|
119 |
-
|
120 |
-
# NMS
|
121 |
-
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
|
122 |
-
dt[2] += time_sync() - t3
|
123 |
-
|
124 |
-
# Second-stage classifier (optional)
|
125 |
-
# pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)
|
126 |
-
|
127 |
-
# Process predictions
|
128 |
-
preds = []
|
129 |
-
for i, det in enumerate(pred): # per image
|
130 |
-
seen += 1
|
131 |
-
if webcam: # batch_size >= 1
|
132 |
-
p, im0, frame = path[i], im0s[i].copy(), dataset.count
|
133 |
-
s += f'{i}: '
|
134 |
-
else:
|
135 |
-
p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)
|
136 |
-
|
137 |
-
p = Path(p) # to Path
|
138 |
-
if save_dir is not None:
|
139 |
-
save_path = str(save_dir / p.name) # im.jpg
|
140 |
-
txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}') # im.txt
|
141 |
-
s += '%gx%g ' % im.shape[2:] # print string
|
142 |
-
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
|
143 |
-
imc = im0.copy() if save_crop else im0 # for save_crop
|
144 |
-
annotator = Annotator(im0, line_width=line_thickness, example=str(names))
|
145 |
-
if len(det):
|
146 |
-
# Rescale boxes from img_size to im0 size
|
147 |
-
det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()
|
148 |
-
|
149 |
-
# Print results
|
150 |
-
for c in det[:, -1].unique():
|
151 |
-
n = (det[:, -1] == c).sum() # detections per class
|
152 |
-
s += f"{n} {names[int(c)]}{'s' * (n > 1)}, " # add to string
|
153 |
-
|
154 |
-
# Write results
|
155 |
-
if save_txt:
|
156 |
-
with open(txt_path + '.txt', 'w') as f:
|
157 |
-
for *xyxy, conf, cls in reversed(det):
|
158 |
-
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
|
159 |
-
preds.append({"class": str(int(cls)), "xmin": int(xyxy[0]), "ymin": int(xyxy[1]), "xmax": int(xyxy[2]),"ymax": int(xyxy[3]), "conf": float(conf)})
|
160 |
-
if save_txt: # Write to file
|
161 |
-
line = (int(cls), *xywh, conf) if save_conf else (cls, *xywh) # label format
|
162 |
-
f.write(('%g ' * len(line)).rstrip() % line + '\n')
|
163 |
-
|
164 |
-
if save_img or save_crop or view_img: # Add bbox to image
|
165 |
-
c = int(cls) # integer class
|
166 |
-
label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
|
167 |
-
annotator.box_label(xyxy, label, color=colors(c, True))
|
168 |
-
if save_crop:
|
169 |
-
save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)
|
170 |
-
else:
|
171 |
-
for *xyxy, conf, cls in reversed(det):
|
172 |
-
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
|
173 |
-
preds.append({"class": str(int(cls)), "xmin": int(xyxy[0]), "ymin": int(xyxy[1]), "xmax": int(xyxy[2]),"ymax": int(xyxy[3]), "conf": float(conf)})
|
174 |
-
|
175 |
-
# Print time (inference-only)
|
176 |
-
# LOGGER.info(f'{s}Done. ({t3 - t2:.3f}s)')
|
177 |
-
|
178 |
-
# Stream results
|
179 |
-
if save_img:
|
180 |
-
im0 = annotator.result()
|
181 |
-
if view_img:
|
182 |
-
cv2.imshow(str(p), im0)
|
183 |
-
cv2.waitKey(1) # 1 millisecond
|
184 |
-
|
185 |
-
# Save results (image with detections)
|
186 |
-
if save_img:
|
187 |
-
if dataset.mode == 'image':
|
188 |
-
cv2.imwrite(save_path, im0)
|
189 |
-
else: # 'video' or 'stream'
|
190 |
-
if vid_path[i] != save_path: # new video
|
191 |
-
vid_path[i] = save_path
|
192 |
-
if isinstance(vid_writer[i], cv2.VideoWriter):
|
193 |
-
vid_writer[i].release() # release previous video writer
|
194 |
-
if vid_cap: # video
|
195 |
-
fps = vid_cap.get(cv2.CAP_PROP_FPS)
|
196 |
-
w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
197 |
-
h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
198 |
-
else: # stream
|
199 |
-
fps, w, h = 30, im0.shape[1], im0.shape[0]
|
200 |
-
save_path = str(Path(save_path).with_suffix('.mp4')) # force *.mp4 suffix on results videos
|
201 |
-
vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
|
202 |
-
vid_writer[i].write(im0)
|
203 |
-
yield preds, save_path
|
204 |
-
# Print results
|
205 |
-
#t = tuple(x / seen * 1E3 for x in dt) # speeds per image
|
206 |
-
#LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}' % t)
|
207 |
-
""" if save_txt or save_img:
|
208 |
-
s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
|
209 |
-
LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
|
210 |
-
if update:
|
211 |
-
strip_optimizer(weights) # update model (to fix SourceChangeWarning) """
|
212 |
-
|
213 |
-
|
214 |
def load_yolo_model(weights, device="cpu", imgsz=[1280, 1280]):
|
215 |
# Load model
|
216 |
device = select_device(device)
|
@@ -232,90 +50,55 @@ def predict(
|
|
232 |
|
233 |
age_model,
|
234 |
model, # model.pt path(s)
|
235 |
-
stride,
|
236 |
-
source=
|
237 |
-
data=ROOT / 'data/coco128.yaml', # dataset.yaml path
|
238 |
imgsz=(640, 640), # inference size (height, width)
|
239 |
conf_thres=0.5, # confidence threshold
|
240 |
iou_thres=0.45, # NMS IOU threshold
|
241 |
max_det=1000, # maximum detections per image
|
242 |
device='cpu', # cuda device, i.e. 0 or 0,1,2,3 or cpu
|
243 |
-
save_img = False,
|
244 |
-
view_img=False, # show results
|
245 |
-
save_txt=False, # save results to *.txt
|
246 |
-
save_conf=False, # save confidences in --save-txt labels
|
247 |
-
save_crop=False, # save cropped prediction boxes
|
248 |
-
nosave=False, # do not save images/videos
|
249 |
classes=None, # filter by class: --class 0, or --class 0 2 3
|
250 |
agnostic_nms=False, # class-agnostic NMS
|
251 |
augment=False, # augmented inference
|
252 |
visualize=False, # visualize features
|
253 |
-
update=False, # update all models
|
254 |
-
project=None, # save results to project/name
|
255 |
-
name='exp', # save results to project/name
|
256 |
-
exist_ok=False, # existing project/name ok, do not increment
|
257 |
-
line_thickness=3, # bounding box thickness (pixels)
|
258 |
-
hide_labels=False, # hide labels
|
259 |
-
hide_conf=False, # hide confidences
|
260 |
half=False, # use FP16 half-precision inference
|
261 |
-
dnn=False, # use OpenCV DNN for ONNX inference
|
262 |
|
263 |
):
|
264 |
-
|
265 |
-
|
266 |
-
source = str(source)
|
267 |
-
|
268 |
-
save_dir = None
|
269 |
-
save_path = None
|
270 |
|
271 |
-
|
272 |
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
#
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()
|
309 |
-
|
310 |
-
for *xyxy, conf, cls in reversed(det):
|
311 |
-
face = im0[int(xyxy[1]):int(xyxy[3]),int(xyxy[0]):int(xyxy[2])]
|
312 |
-
face_img = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
|
313 |
-
im = test_transforms(face_img).unsqueeze_(0)
|
314 |
-
with torch.no_grad():
|
315 |
-
y = age_model(im)
|
316 |
-
|
317 |
-
age = y[0]
|
318 |
-
|
319 |
-
preds.append({"class": str(int(age)), "xmin": int(xyxy[0]), "ymin": int(xyxy[1]), "xmax": int(xyxy[2]),"ymax": int(xyxy[3]), "conf": float(conf)})
|
320 |
-
|
321 |
-
yield preds, save_path
|
|
|
18 |
from yolov5.utils.plots import Annotator, colors, save_one_box
|
19 |
from yolov5.utils.general import (check_img_size,
|
20 |
increment_path, non_max_suppression, scale_coords, xyxy2xywh)
|
21 |
+
from yolov5.utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages, pil_to_cv
|
22 |
from yolov5.models.common import DetectMultiBackend
|
23 |
import torchvision
|
24 |
|
|
|
29 |
torchvision.transforms.Resize((224, 224)),
|
30 |
])
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
def load_yolo_model(weights, device="cpu", imgsz=[1280, 1280]):
|
33 |
# Load model
|
34 |
device = select_device(device)
|
|
|
50 |
|
51 |
age_model,
|
52 |
model, # model.pt path(s)
|
53 |
+
stride,
|
54 |
+
source=None, # PIL Image
|
|
|
55 |
imgsz=(640, 640), # inference size (height, width)
|
56 |
conf_thres=0.5, # confidence threshold
|
57 |
iou_thres=0.45, # NMS IOU threshold
|
58 |
max_det=1000, # maximum detections per image
|
59 |
device='cpu', # cuda device, i.e. 0 or 0,1,2,3 or cpu
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
classes=None, # filter by class: --class 0, or --class 0 2 3
|
61 |
agnostic_nms=False, # class-agnostic NMS
|
62 |
augment=False, # augmented inference
|
63 |
visualize=False, # visualize features
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
half=False, # use FP16 half-precision inference
|
|
|
65 |
|
66 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
+
im, im0 = pil_to_cv(source, img_size=imgsz[0], stride=stride)
|
69 |
|
70 |
+
im = torch.from_numpy(im).to(device)
|
71 |
+
im = im.half() if half else im.float() # uint8 to fp16/32
|
72 |
+
im /= 255 # 0 - 255 to 0.0 - 1.0
|
73 |
+
if len(im.shape) == 3:
|
74 |
+
im = im[None] # expand for batch dim
|
75 |
+
|
76 |
+
# Inference
|
77 |
+
visualize = False
|
78 |
+
pred = model(im, augment=augment, visualize=visualize)
|
79 |
+
|
80 |
+
# NMS
|
81 |
+
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
|
82 |
+
|
83 |
+
# Process predictions
|
84 |
+
preds = []
|
85 |
+
for i, det in enumerate(pred): # per image
|
86 |
+
|
87 |
+
# im0 = im0.copy()
|
88 |
+
|
89 |
+
if len(det):
|
90 |
+
# Rescale boxes from img_size to im0 size
|
91 |
+
det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()
|
92 |
+
|
93 |
+
for *xyxy, conf, cls in reversed(det):
|
94 |
+
face = im0[int(xyxy[1]):int(xyxy[3]),int(xyxy[0]):int(xyxy[2])]
|
95 |
+
face_img = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
|
96 |
+
im = test_transforms(face_img).unsqueeze_(0)
|
97 |
+
with torch.no_grad():
|
98 |
+
y = age_model(im)
|
99 |
+
|
100 |
+
age = y[0]
|
101 |
+
|
102 |
+
preds.append({"class": str(int(age)), "xmin": int(xyxy[0]), "ymin": int(xyxy[1]), "xmax": int(xyxy[2]),"ymax": int(xyxy[3]), "conf": float(conf)})
|
103 |
+
|
104 |
+
return preds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
yolov5/utils/datasets.py
CHANGED
@@ -87,6 +87,19 @@ def exif_transpose(image):
|
|
87 |
image.info["exif"] = exif.tobytes()
|
88 |
return image
|
89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
class LoadImages:
|
91 |
# YOLOv5 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4`
|
92 |
def __init__(self, path, img_size=640, stride=32, auto=True):
|
|
|
87 |
image.info["exif"] = exif.tobytes()
|
88 |
return image
|
89 |
|
90 |
+
|
91 |
+
def pil_to_cv(pil_img, img_size=320, stride=32, auto=True):
|
92 |
+
np_img = np.array(pil_img)
|
93 |
+
|
94 |
+
img0 = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)
|
95 |
+
|
96 |
+
img = letterbox(img0, img_size, stride=stride, auto=auto)[0]
|
97 |
+
img = img.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
|
98 |
+
img = np.ascontiguousarray(img)
|
99 |
+
|
100 |
+
return img, img0
|
101 |
+
|
102 |
+
|
103 |
class LoadImages:
|
104 |
# YOLOv5 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4`
|
105 |
def __init__(self, path, img_size=640, stride=32, auto=True):
|