ultralytics 8.2.59 use Results.save_txt for validation (#14496)
Co-authored-by: UltralyticsAssistant <web@ultralytics.com> Co-authored-by: Glenn Jocher <glenn.jocher@ultralytics.com>
This commit is contained in:
parent
ebf7dcf5a8
commit
bfcd85323d
7 changed files with 83 additions and 32 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
|
||||
__version__ = "8.2.58"
|
||||
__version__ = "8.2.59"
|
||||
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -160,8 +160,12 @@ class DetectionValidator(BaseValidator):
|
|||
if self.args.save_json:
|
||||
self.pred_to_json(predn, batch["im_file"][si])
|
||||
if self.args.save_txt:
|
||||
file = self.save_dir / "labels" / f'{Path(batch["im_file"][si]).stem}.txt'
|
||||
self.save_one_txt(predn, self.args.save_conf, pbatch["ori_shape"], file)
|
||||
self.save_one_txt(
|
||||
predn,
|
||||
self.args.save_conf,
|
||||
pbatch["ori_shape"],
|
||||
self.save_dir / "labels" / f'{Path(batch["im_file"][si]).stem}.txt',
|
||||
)
|
||||
|
||||
def finalize_metrics(self, *args, **kwargs):
|
||||
"""Set final values for metrics speed and confusion matrix."""
|
||||
|
|
@ -261,12 +265,14 @@ class DetectionValidator(BaseValidator):
|
|||
|
||||
def save_one_txt(self, predn, save_conf, shape, file):
|
||||
"""Save YOLO detections to a txt file in normalized coordinates in a specific format."""
|
||||
gn = torch.tensor(shape)[[1, 0, 1, 0]] # normalization gain whwh
|
||||
for *xyxy, conf, cls in predn.tolist():
|
||||
xywh = (ops.xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
|
||||
line = (cls, *xywh, conf) if save_conf else (cls, *xywh) # label format
|
||||
with open(file, "a") as f:
|
||||
f.write(("%g " * len(line)).rstrip() % line + "\n")
|
||||
from ultralytics.engine.results import Results
|
||||
|
||||
Results(
|
||||
np.zeros((shape[0], shape[1]), dtype=np.uint8),
|
||||
path=None,
|
||||
names=self.names,
|
||||
boxes=predn[:, :6],
|
||||
).save_txt(file, save_conf=save_conf)
|
||||
|
||||
def pred_to_json(self, predn, filename):
|
||||
"""Serialize YOLO predictions to COCO json format."""
|
||||
|
|
|
|||
|
|
@ -130,13 +130,19 @@ class OBBValidator(DetectionValidator):
|
|||
|
||||
def save_one_txt(self, predn, save_conf, shape, file):
|
||||
"""Save YOLO detections to a txt file in normalized coordinates in a specific format."""
|
||||
gn = torch.tensor(shape)[[1, 0]] # normalization gain whwh
|
||||
for *xywh, conf, cls, angle in predn.tolist():
|
||||
xywha = torch.tensor([*xywh, angle]).view(1, 5)
|
||||
xyxyxyxy = (ops.xywhr2xyxyxyxy(xywha) / gn).view(-1).tolist() # normalized xywh
|
||||
line = (cls, *xyxyxyxy, conf) if save_conf else (cls, *xyxyxyxy) # label format
|
||||
with open(file, "a") as f:
|
||||
f.write(("%g " * len(line)).rstrip() % line + "\n")
|
||||
import numpy as np
|
||||
|
||||
from ultralytics.engine.results import Results
|
||||
|
||||
rboxes = torch.cat([predn[:, :4], predn[:, -1:]], dim=-1)
|
||||
# xywh, r, conf, cls
|
||||
obb = torch.cat([rboxes, predn[:, 4:6]], dim=-1)
|
||||
Results(
|
||||
np.zeros((shape[0], shape[1]), dtype=np.uint8),
|
||||
path=None,
|
||||
names=self.names,
|
||||
obb=obb,
|
||||
).save_txt(file, save_conf=save_conf)
|
||||
|
||||
def eval_json(self, stats):
|
||||
"""Evaluates YOLO output in JSON format and returns performance statistics."""
|
||||
|
|
|
|||
|
|
@ -147,8 +147,14 @@ class PoseValidator(DetectionValidator):
|
|||
# Save
|
||||
if self.args.save_json:
|
||||
self.pred_to_json(predn, batch["im_file"][si])
|
||||
# if self.args.save_txt:
|
||||
# save_one_txt(predn, save_conf, shape, file=save_dir / 'labels' / f'{path.stem}.txt')
|
||||
if self.args.save_txt:
|
||||
self.save_one_txt(
|
||||
predn,
|
||||
pred_kpts,
|
||||
self.args.save_conf,
|
||||
pbatch["ori_shape"],
|
||||
self.save_dir / "labels" / f'{Path(batch["im_file"][si]).stem}.txt',
|
||||
)
|
||||
|
||||
def _process_batch(self, detections, gt_bboxes, gt_cls, pred_kpts=None, gt_kpts=None):
|
||||
"""
|
||||
|
|
@ -217,6 +223,18 @@ class PoseValidator(DetectionValidator):
|
|||
on_plot=self.on_plot,
|
||||
) # pred
|
||||
|
||||
def save_one_txt(self, predn, pred_kpts, save_conf, shape, file):
|
||||
"""Save YOLO detections to a txt file in normalized coordinates in a specific format."""
|
||||
from ultralytics.engine.results import Results
|
||||
|
||||
Results(
|
||||
np.zeros((shape[0], shape[1]), dtype=np.uint8),
|
||||
path=None,
|
||||
names=self.names,
|
||||
boxes=predn[:, :6],
|
||||
keypoints=pred_kpts,
|
||||
).save_txt(file, save_conf=save_conf)
|
||||
|
||||
def pred_to_json(self, predn, filename):
|
||||
"""Converts YOLO predictions to COCO JSON format."""
|
||||
stem = Path(filename).stem
|
||||
|
|
|
|||
|
|
@ -48,9 +48,8 @@ class SegmentationValidator(DetectionValidator):
|
|||
self.plot_masks = []
|
||||
if self.args.save_json:
|
||||
check_requirements("pycocotools>=2.0.6")
|
||||
self.process = ops.process_mask_upsample # more accurate
|
||||
else:
|
||||
self.process = ops.process_mask # faster
|
||||
# more accurate vs faster
|
||||
self.process = ops.process_mask_upsample if self.args.save_json or self.args.save_txt else ops.process_mask
|
||||
self.stats = dict(tp_m=[], tp=[], conf=[], pred_cls=[], target_cls=[], target_img=[])
|
||||
|
||||
def get_desc(self):
|
||||
|
|
@ -148,14 +147,23 @@ class SegmentationValidator(DetectionValidator):
|
|||
|
||||
# Save
|
||||
if self.args.save_json:
|
||||
pred_masks = ops.scale_image(
|
||||
pred_masks.permute(1, 2, 0).contiguous().cpu().numpy(),
|
||||
pbatch["ori_shape"],
|
||||
ratio_pad=batch["ratio_pad"][si],
|
||||
self.pred_to_json(
|
||||
predn,
|
||||
batch["im_file"][si],
|
||||
ops.scale_image(
|
||||
pred_masks.permute(1, 2, 0).contiguous().cpu().numpy(),
|
||||
pbatch["ori_shape"],
|
||||
ratio_pad=batch["ratio_pad"][si],
|
||||
),
|
||||
)
|
||||
if self.args.save_txt:
|
||||
self.save_one_txt(
|
||||
predn,
|
||||
pred_masks,
|
||||
self.args.save_conf,
|
||||
pbatch["ori_shape"],
|
||||
self.save_dir / "labels" / f'{Path(batch["im_file"][si]).stem}.txt',
|
||||
)
|
||||
self.pred_to_json(predn, batch["im_file"][si], pred_masks)
|
||||
# if self.args.save_txt:
|
||||
# save_one_txt(predn, save_conf, shape, file=save_dir / 'labels' / f'{path.stem}.txt')
|
||||
|
||||
def finalize_metrics(self, *args, **kwargs):
|
||||
"""Sets speed and confusion matrix for evaluation metrics."""
|
||||
|
|
@ -235,6 +243,18 @@ class SegmentationValidator(DetectionValidator):
|
|||
) # pred
|
||||
self.plot_masks.clear()
|
||||
|
||||
def save_one_txt(self, predn, pred_masks, save_conf, shape, file):
|
||||
"""Save YOLO detections to a txt file in normalized coordinates in a specific format."""
|
||||
from ultralytics.engine.results import Results
|
||||
|
||||
Results(
|
||||
np.zeros((shape[0], shape[1]), dtype=np.uint8),
|
||||
path=None,
|
||||
names=self.names,
|
||||
boxes=predn[:, :6],
|
||||
masks=pred_masks,
|
||||
).save_txt(file, save_conf=save_conf)
|
||||
|
||||
def pred_to_json(self, predn, filename, pred_masks):
|
||||
"""
|
||||
Save one JSON result.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue