Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yolov5
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
yolov5
Commits
354a97e4
提交
354a97e4
authored
9月 03, 2020
作者:
Glenn Jocher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Create sotabench.py
上级
d6817995
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
311 行增加
和
0 行删除
+311
-0
sotabench.py
sotabench.py
+311
-0
没有找到文件。
sotabench.py
0 → 100644
浏览文件 @
354a97e4
import
argparse
import
glob
import
json
import
os
import
shutil
from
pathlib
import
Path
import
numpy
as
np
import
torch
import
yaml
from
tqdm
import
tqdm
from
models.experimental
import
attempt_load
from
utils.datasets
import
create_dataloader
from
utils.general
import
(
coco80_to_coco91_class
,
check_dataset
,
check_file
,
check_img_size
,
compute_loss
,
non_max_suppression
,
scale_coords
,
xyxy2xywh
,
clip_coords
,
plot_images
,
xywh2xyxy
,
box_iou
,
output_to_target
,
ap_per_class
,
set_logging
)
from
utils.torch_utils
import
select_device
,
time_synchronized
from
sotabencheval.object_detection
import
COCOEvaluator
from
sotabencheval.utils
import
is_server
DATA_ROOT
=
'./.data/vision/coco'
if
is_server
()
else
'../coco'
# sotabench data dir
def
test
(
data
,
weights
=
None
,
batch_size
=
16
,
imgsz
=
640
,
conf_thres
=
0.001
,
iou_thres
=
0.6
,
# for NMS
save_json
=
False
,
single_cls
=
False
,
augment
=
False
,
verbose
=
False
,
model
=
None
,
dataloader
=
None
,
save_dir
=
''
,
merge
=
False
,
save_txt
=
False
):
# Initialize/load model and set device
training
=
model
is
not
None
if
training
:
# called by train.py
device
=
next
(
model
.
parameters
())
.
device
# get model device
else
:
# called directly
set_logging
()
device
=
select_device
(
opt
.
device
,
batch_size
=
batch_size
)
merge
,
save_txt
=
opt
.
merge
,
opt
.
save_txt
# use Merge NMS, save *.txt labels
if
save_txt
:
out
=
Path
(
'inference/output'
)
if
os
.
path
.
exists
(
out
):
shutil
.
rmtree
(
out
)
# delete output folder
os
.
makedirs
(
out
)
# make new output folder
# Remove previous
for
f
in
glob
.
glob
(
str
(
Path
(
save_dir
)
/
'test_batch*.jpg'
)):
os
.
remove
(
f
)
# Load model
model
=
attempt_load
(
weights
,
map_location
=
device
)
# load FP32 model
imgsz
=
check_img_size
(
imgsz
,
s
=
model
.
stride
.
max
())
# check img_size
# Multi-GPU disabled, incompatible with .half() https://github.com/ultralytics/yolov5/issues/99
# if device.type != 'cpu' and torch.cuda.device_count() > 1:
# model = nn.DataParallel(model)
# Half
half
=
device
.
type
!=
'cpu'
# half precision only supported on CUDA
if
half
:
model
.
half
()
# Configure
model
.
eval
()
with
open
(
data
)
as
f
:
data
=
yaml
.
load
(
f
,
Loader
=
yaml
.
FullLoader
)
# model dict
check_dataset
(
data
)
# check
nc
=
1
if
single_cls
else
int
(
data
[
'nc'
])
# number of classes
iouv
=
torch
.
linspace
(
0.5
,
0.95
,
10
)
.
to
(
device
)
# iou vector for mAP@0.5:0.95
niou
=
iouv
.
numel
()
# Dataloader
if
not
training
:
img
=
torch
.
zeros
((
1
,
3
,
imgsz
,
imgsz
),
device
=
device
)
# init img
_
=
model
(
img
.
half
()
if
half
else
img
)
if
device
.
type
!=
'cpu'
else
None
# run once
path
=
data
[
'test'
]
if
opt
.
task
==
'test'
else
data
[
'val'
]
# path to val/test images
dataloader
=
create_dataloader
(
path
,
imgsz
,
batch_size
,
model
.
stride
.
max
(),
opt
,
hyp
=
None
,
augment
=
False
,
cache
=
True
,
pad
=
0.5
,
rect
=
True
)[
0
]
seen
=
0
names
=
model
.
names
if
hasattr
(
model
,
'names'
)
else
model
.
module
.
names
coco91class
=
coco80_to_coco91_class
()
s
=
(
'
%20
s'
+
'
%12
s'
*
6
)
%
(
'Class'
,
'Images'
,
'Targets'
,
'P'
,
'R'
,
'mAP@.5'
,
'mAP@.5:.95'
)
p
,
r
,
f1
,
mp
,
mr
,
map50
,
map
,
t0
,
t1
=
0.
,
0.
,
0.
,
0.
,
0.
,
0.
,
0.
,
0.
,
0.
loss
=
torch
.
zeros
(
3
,
device
=
device
)
jdict
,
stats
,
ap
,
ap_class
=
[],
[],
[],
[]
evaluator
=
COCOEvaluator
(
root
=
DATA_ROOT
,
model_name
=
opt
.
weights
.
replace
(
'.pt'
,
''
))
for
batch_i
,
(
img
,
targets
,
paths
,
shapes
)
in
enumerate
(
tqdm
(
dataloader
,
desc
=
s
)):
img
=
img
.
to
(
device
,
non_blocking
=
True
)
img
=
img
.
half
()
if
half
else
img
.
float
()
# uint8 to fp16/32
img
/=
255.0
# 0 - 255 to 0.0 - 1.0
targets
=
targets
.
to
(
device
)
nb
,
_
,
height
,
width
=
img
.
shape
# batch size, channels, height, width
whwh
=
torch
.
Tensor
([
width
,
height
,
width
,
height
])
.
to
(
device
)
# Disable gradients
with
torch
.
no_grad
():
# Run model
t
=
time_synchronized
()
inf_out
,
train_out
=
model
(
img
,
augment
=
augment
)
# inference and training outputs
t0
+=
time_synchronized
()
-
t
# Compute loss
if
training
:
# if model has loss hyperparameters
loss
+=
compute_loss
([
x
.
float
()
for
x
in
train_out
],
targets
,
model
)[
1
][:
3
]
# GIoU, obj, cls
# Run NMS
t
=
time_synchronized
()
output
=
non_max_suppression
(
inf_out
,
conf_thres
=
conf_thres
,
iou_thres
=
iou_thres
,
merge
=
merge
)
t1
+=
time_synchronized
()
-
t
# Statistics per image
for
si
,
pred
in
enumerate
(
output
):
labels
=
targets
[
targets
[:,
0
]
==
si
,
1
:]
nl
=
len
(
labels
)
tcls
=
labels
[:,
0
]
.
tolist
()
if
nl
else
[]
# target class
seen
+=
1
if
pred
is
None
:
if
nl
:
stats
.
append
((
torch
.
zeros
(
0
,
niou
,
dtype
=
torch
.
bool
),
torch
.
Tensor
(),
torch
.
Tensor
(),
tcls
))
continue
# Append to text file
if
save_txt
:
gn
=
torch
.
tensor
(
shapes
[
si
][
0
])[[
1
,
0
,
1
,
0
]]
# normalization gain whwh
x
=
pred
.
clone
()
x
[:,
:
4
]
=
scale_coords
(
img
[
si
]
.
shape
[
1
:],
x
[:,
:
4
],
shapes
[
si
][
0
],
shapes
[
si
][
1
])
# to original
for
*
xyxy
,
conf
,
cls
in
x
:
xywh
=
(
xyxy2xywh
(
torch
.
tensor
(
xyxy
)
.
view
(
1
,
4
))
/
gn
)
.
view
(
-
1
)
.
tolist
()
# normalized xywh
with
open
(
str
(
out
/
Path
(
paths
[
si
])
.
stem
)
+
'.txt'
,
'a'
)
as
f
:
f
.
write
((
'
%
g '
*
5
+
'
\n
'
)
%
(
cls
,
*
xywh
))
# label format
# Clip boxes to image bounds
clip_coords
(
pred
,
(
height
,
width
))
# Append to pycocotools JSON dictionary
if
save_json
:
# [{"image_id": 42, "category_id": 18, "bbox": [258.15, 41.29, 348.26, 243.78], "score": 0.236}, ...
image_id
=
Path
(
paths
[
si
])
.
stem
box
=
pred
[:,
:
4
]
.
clone
()
# xyxy
scale_coords
(
img
[
si
]
.
shape
[
1
:],
box
,
shapes
[
si
][
0
],
shapes
[
si
][
1
])
# to original shape
box
=
xyxy2xywh
(
box
)
# xywh
box
[:,
:
2
]
-=
box
[:,
2
:]
/
2
# xy center to top-left corner
for
p
,
b
in
zip
(
pred
.
tolist
(),
box
.
tolist
()):
result
=
{
'image_id'
:
int
(
image_id
)
if
image_id
.
isnumeric
()
else
image_id
,
'category_id'
:
coco91class
[
int
(
p
[
5
])],
'bbox'
:
[
round
(
x
,
3
)
for
x
in
b
],
'score'
:
round
(
p
[
4
],
5
)}
jdict
.
append
(
result
)
#evaluator.add([result])
#if evaluator.cache_exists:
# break
# # Assign all predictions as incorrect
# correct = torch.zeros(pred.shape[0], niou, dtype=torch.bool, device=device)
# if nl:
# detected = [] # target indices
# tcls_tensor = labels[:, 0]
#
# # target boxes
# tbox = xywh2xyxy(labels[:, 1:5]) * whwh
#
# # Per target class
# for cls in torch.unique(tcls_tensor):
# ti = (cls == tcls_tensor).nonzero(as_tuple=False).view(-1) # prediction indices
# pi = (cls == pred[:, 5]).nonzero(as_tuple=False).view(-1) # target indices
#
# # Search for detections
# if pi.shape[0]:
# # Prediction to target ious
# ious, i = box_iou(pred[pi, :4], tbox[ti]).max(1) # best ious, indices
#
# # Append detections
# detected_set = set()
# for j in (ious > iouv[0]).nonzero(as_tuple=False):
# d = ti[i[j]] # detected target
# if d.item() not in detected_set:
# detected_set.add(d.item())
# detected.append(d)
# correct[pi[j]] = ious[j] > iouv # iou_thres is 1xn
# if len(detected) == nl: # all targets already located in image
# break
#
# # Append statistics (correct, conf, pcls, tcls)
# stats.append((correct.cpu(), pred[:, 4].cpu(), pred[:, 5].cpu(), tcls))
# # Plot images
# if batch_i < 1:
# f = Path(save_dir) / ('test_batch%g_gt.jpg' % batch_i) # filename
# plot_images(img, targets, paths, str(f), names) # ground truth
# f = Path(save_dir) / ('test_batch%g_pred.jpg' % batch_i)
# plot_images(img, output_to_target(output, width, height), paths, str(f), names) # predictions
evaluator
.
add
(
jdict
)
evaluator
.
save
()
# # Compute statistics
# stats = [np.concatenate(x, 0) for x in zip(*stats)] # to numpy
# if len(stats) and stats[0].any():
# p, r, ap, f1, ap_class = ap_per_class(*stats)
# p, r, ap50, ap = p[:, 0], r[:, 0], ap[:, 0], ap.mean(1) # [P, R, AP@0.5, AP@0.5:0.95]
# mp, mr, map50, map = p.mean(), r.mean(), ap50.mean(), ap.mean()
# nt = np.bincount(stats[3].astype(np.int64), minlength=nc) # number of targets per class
# else:
# nt = torch.zeros(1)
#
# # Print results
# pf = '%20s' + '%12.3g' * 6 # print format
# print(pf % ('all', seen, nt.sum(), mp, mr, map50, map))
#
# # Print results per class
# if verbose and nc > 1 and len(stats):
# for i, c in enumerate(ap_class):
# print(pf % (names[c], seen, nt[c], p[i], r[i], ap50[i], ap[i]))
#
# # Print speeds
# t = tuple(x / seen * 1E3 for x in (t0, t1, t0 + t1)) + (imgsz, imgsz, batch_size) # tuple
# if not training:
# print('Speed: %.1f/%.1f/%.1f ms inference/NMS/total per %gx%g image at batch-size %g' % t)
#
# # Save JSON
# if save_json and len(jdict):
# f = 'detections_val2017_%s_results.json' % \
# (weights.split(os.sep)[-1].replace('.pt', '') if isinstance(weights, str) else '') # filename
# print('\nCOCO mAP with pycocotools... saving %s...' % f)
# with open(f, 'w') as file:
# json.dump(jdict, file)
#
# try: # https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoEvalDemo.ipynb
# from pycocotools.coco import COCO
# from pycocotools.cocoeval import COCOeval
#
# imgIds = [int(Path(x).stem) for x in dataloader.dataset.img_files]
# cocoGt = COCO(glob.glob('../coco/annotations/instances_val*.json')[0]) # initialize COCO ground truth api
# cocoDt = cocoGt.loadRes(f) # initialize COCO pred api
# cocoEval = COCOeval(cocoGt, cocoDt, 'bbox')
# cocoEval.params.imgIds = imgIds # image IDs to evaluate
# cocoEval.evaluate()
# cocoEval.accumulate()
# cocoEval.summarize()
# map, map50 = cocoEval.stats[:2] # update results (mAP@0.5:0.95, mAP@0.5)
# except Exception as e:
# print('ERROR: pycocotools unable to run: %s' % e)
#
# # Return results
# model.float() # for training
# maps = np.zeros(nc) + map
# for i, c in enumerate(ap_class):
# maps[c] = ap[i]
# return (mp, mr, map50, map, *(loss.cpu() / len(dataloader)).tolist()), maps, t
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
prog
=
'test.py'
)
parser
.
add_argument
(
'--weights'
,
nargs
=
'+'
,
type
=
str
,
default
=
'yolov5s.pt'
,
help
=
'model.pt path(s)'
)
parser
.
add_argument
(
'--data'
,
type
=
str
,
default
=
'data/coco.yaml'
,
help
=
'*.data path'
)
parser
.
add_argument
(
'--batch-size'
,
type
=
int
,
default
=
32
,
help
=
'size of each image batch'
)
parser
.
add_argument
(
'--img-size'
,
type
=
int
,
default
=
640
,
help
=
'inference size (pixels)'
)
parser
.
add_argument
(
'--conf-thres'
,
type
=
float
,
default
=
0.001
,
help
=
'object confidence threshold'
)
parser
.
add_argument
(
'--iou-thres'
,
type
=
float
,
default
=
0.65
,
help
=
'IOU threshold for NMS'
)
parser
.
add_argument
(
'--save-json'
,
action
=
'store_true'
,
help
=
'save a cocoapi-compatible JSON results file'
)
parser
.
add_argument
(
'--task'
,
default
=
'val'
,
help
=
"'val', 'test', 'study'"
)
parser
.
add_argument
(
'--device'
,
default
=
''
,
help
=
'cuda device, i.e. 0 or 0,1,2,3 or cpu'
)
parser
.
add_argument
(
'--single-cls'
,
action
=
'store_true'
,
help
=
'treat as single-class dataset'
)
parser
.
add_argument
(
'--augment'
,
action
=
'store_true'
,
help
=
'augmented inference'
)
parser
.
add_argument
(
'--merge'
,
action
=
'store_true'
,
help
=
'use Merge NMS'
)
parser
.
add_argument
(
'--verbose'
,
action
=
'store_true'
,
help
=
'report mAP by class'
)
parser
.
add_argument
(
'--save-txt'
,
action
=
'store_true'
,
help
=
'save results to *.txt'
)
opt
=
parser
.
parse_args
()
opt
.
save_json
|=
opt
.
data
.
endswith
(
'coco.yaml'
)
opt
.
data
=
check_file
(
opt
.
data
)
# check file
print
(
opt
)
if
opt
.
task
in
[
'val'
,
'test'
]:
# run normally
test
(
opt
.
data
,
opt
.
weights
,
opt
.
batch_size
,
opt
.
img_size
,
opt
.
conf_thres
,
opt
.
iou_thres
,
opt
.
save_json
,
opt
.
single_cls
,
opt
.
augment
,
opt
.
verbose
)
elif
opt
.
task
==
'study'
:
# run over a range of settings and save/plot
for
weights
in
[
'yolov5s.pt'
,
'yolov5m.pt'
,
'yolov5l.pt'
,
'yolov5x.pt'
]:
f
=
'study_
%
s_
%
s.txt'
%
(
Path
(
opt
.
data
)
.
stem
,
Path
(
weights
)
.
stem
)
# filename to save to
x
=
list
(
range
(
320
,
800
,
64
))
# x axis
y
=
[]
# y axis
for
i
in
x
:
# img-size
print
(
'
\n
Running
%
s point
%
s...'
%
(
f
,
i
))
r
,
_
,
t
=
test
(
opt
.
data
,
weights
,
opt
.
batch_size
,
i
,
opt
.
conf_thres
,
opt
.
iou_thres
,
opt
.
save_json
)
y
.
append
(
r
+
t
)
# results and times
np
.
savetxt
(
f
,
y
,
fmt
=
'
%10.4
g'
)
# save
os
.
system
(
'zip -r study.zip study_*.txt'
)
# utils.general.plot_study_txt(f, x) # plot
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论