2022-07-06 23:23:27 +08:00
import argparse
import json
import os
from pathlib import Path
from threading import Thread
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 , check_requirements , \
box_iou , non_max_suppression , scale_coords , xyxy2xywh , xywh2xyxy , set_logging , increment_path , colorstr
from utils . metrics import ap_per_class , ConfusionMatrix
2024-09-15 14:20:39 +08:00
from utils . plots import plot_images , output_to_target , plot_study_txt , append_to_txt
2022-07-06 23:23:27 +08:00
from utils . torch_utils import select_device , time_synchronized , TracedModel
def test ( data ,
weights = None ,
batch_size = 32 ,
imgsz = 640 ,
conf_thres = 0.001 ,
2024-10-14 15:32:25 +08:00
iou_thres = 0.6 , # used for NMS
2022-07-06 23:23:27 +08:00
save_json = False ,
single_cls = False ,
augment = False ,
verbose = False ,
model = None ,
dataloader = None ,
save_dir = Path ( ' ' ) , # for saving images
save_txt = False , # for auto-labelling
save_hybrid = False , # for hybrid auto-labelling
save_conf = False , # save auto-label confidences
plots = True ,
wandb_logger = None ,
compute_loss = None ,
half_precision = True ,
trace = False ,
2022-09-17 02:14:01 +08:00
is_coco = False ,
2024-11-04 16:08:35 +08:00
v5_metric = False ,
* * kwargs ) :
2022-07-06 23:23:27 +08:00
# Initialize/load model and set device
2024-11-04 16:08:35 +08:00
hyp = kwargs [ ' hyp ' ]
2022-07-06 23:23:27 +08:00
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 )
# Directories
2024-10-15 19:40:02 +08:00
if opt . save_path == ' ' :
save_dir = Path ( increment_path ( Path ( opt . project ) / opt . name , exist_ok = opt . exist_ok ) ) # increment run
else :
2024-10-21 20:57:07 +08:00
save_dir = Path ( increment_path ( os . path . join ( opt . save_path , Path ( opt . project ) , opt . name ) , exist_ok = opt . exist_ok ) )
2024-10-15 19:40:02 +08:00
try : # no suduer can fail
( save_dir / ' labels ' if save_txt else save_dir ) . mkdir ( parents = True , exist_ok = True ) # make dir
except Exception as e :
print ( " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " , e )
2022-07-06 23:23:27 +08:00
# Load model
model = attempt_load ( weights , map_location = device ) # load FP32 model
gs = max ( int ( model . stride . max ( ) ) , 32 ) # grid size (max stride)
imgsz = check_img_size ( imgsz , s = gs ) # check img_size
if trace :
2024-10-21 20:57:07 +08:00
model = TracedModel ( model , device , imgsz , opt . input_channels )
2022-07-06 23:23:27 +08:00
2024-08-27 18:58:16 +08:00
#torch.backends.cudnn.benchmark = True ##uses the inbuilt cudnn auto-tuner to find the fastest convolution algorithms. -
2022-07-06 23:23:27 +08:00
# Half
2024-08-27 18:58:16 +08:00
half = device . type != ' cpu ' and half_precision # half precision only supported on CUDA @@ HK : TODO what are the consequences add :
2022-07-06 23:23:27 +08:00
if half :
model . half ( )
# Configure
model . eval ( )
if isinstance ( data , str ) :
is_coco = data . endswith ( ' coco.yaml ' )
with open ( data ) as f :
data = yaml . load ( f , Loader = yaml . SafeLoader )
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 ( )
# Logging
log_imgs = 0
if wandb_logger and wandb_logger . wandb :
log_imgs = min ( wandb_logger . log_imgs , 100 )
# Dataloader
2024-10-14 15:32:25 +08:00
2022-07-06 23:23:27 +08:00
if not training :
if device . type != ' cpu ' :
2024-10-21 20:57:07 +08:00
model ( torch . zeros ( 1 , opt . input_channels , imgsz , imgsz ) . to ( device ) . type_as ( next ( model . parameters ( ) ) ) ) # run once
2022-07-06 23:23:27 +08:00
task = opt . task if opt . task in ( ' train ' , ' val ' , ' test ' ) else ' val ' # path to train/val/test images
2024-11-04 16:08:35 +08:00
hyp = dict ( )
hyp [ ' person_size_small_medium_th ' ] = 32 * 32
hyp [ ' car_size_small_medium_th ' ] = 44 * 44
2024-09-23 16:23:13 +08:00
hyp [ ' img_percentile_removal ' ] = 0.3
hyp [ ' beta ' ] = 0.3
2024-10-21 20:57:07 +08:00
hyp [ ' gamma ' ] = 80 # dummy anyway augmentation is disabled
hyp [ ' gamma_liklihood ' ] = 0.01
2024-12-01 23:37:59 +08:00
hyp [ ' random_pad ' ] = True
hyp [ ' copy_paste ' ] = False
2024-10-21 20:57:07 +08:00
# augment=False explicit no augmentation to test
dataloader = create_dataloader ( data [ task ] , imgsz , batch_size , gs , opt , hyp , pad = 0.5 , augment = False , rect = False , #rect was True # HK@@@ TODO : why pad =0.5?? only effective in rect=True in test time ? https://github.com/ultralytics/ultralytics/issues/13271
2024-10-14 15:32:25 +08:00
prefix = colorstr ( f ' { task } : ' ) , rel_path_images = data [ ' path ' ] , num_cls = data [ ' nc ' ] ) [ 0 ]
2022-07-06 23:23:27 +08:00
2022-09-17 02:14:01 +08:00
if v5_metric :
print ( " Testing with YOLOv5 AP metric... " )
2022-07-06 23:23:27 +08:00
seen = 0
2024-11-04 16:08:35 +08:00
confusion_matrix = ConfusionMatrix ( nc = nc , conf = conf_thres , iou_thres = iou_thres ) # HK per conf per iou_thresh
2022-07-06 23:23:27 +08:00
names = { k : v for k , v in enumerate ( model . names if hasattr ( model , ' names ' ) else model . module . names ) }
coco91class = coco80_to_coco91_class ( )
s = ( ' %20s ' + ' %12s ' * 6 ) % ( ' Class ' , ' Images ' , ' Labels ' , ' 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 , wandb_images = [ ] , [ ] , [ ] , [ ] , [ ]
2024-11-04 16:08:35 +08:00
stats_all_large , stats_person_medium = [ ] , [ ]
2022-07-06 23:23:27 +08:00
for batch_i , ( img , targets , paths , shapes ) in enumerate ( tqdm ( dataloader , desc = s ) ) :
img = img . to ( device , non_blocking = True )
2024-08-19 20:56:20 +08:00
img = img . half ( ) if half else img . float ( )
# uint8 to fp16/32
# img /= 255.0 # 0 - 255 to 0.0 - 1.0 c# already done inside dataloader
2022-07-06 23:23:27 +08:00
targets = targets . to ( device )
nb , _ , height , width = img . shape # batch size, channels, height, width
with torch . no_grad ( ) :
# Run model
t = time_synchronized ( )
2024-09-15 14:20:39 +08:00
out , train_out = model ( img , augment = augment ) # inference(4 coordination, obj conf, cls conf ) and training outputs(batch_size, anchor per scale, x,y dim of scale out 40x40 ,n_classes-conf+1-objectness+4-bbox ) over 3 scales diferent outputs (2,2,80,80,7), (2,2,40,40,7) : 640/8=40
2022-07-06 23:23:27 +08:00
t0 + = time_synchronized ( ) - t
2024-09-15 14:20:39 +08:00
# out coco 80 classes : [1, 25200, 85] [batch, proposals_3_scales,4_box__coord+1_obj_score + n x classes]
2022-07-06 23:23:27 +08:00
# Compute loss
if compute_loss :
loss + = compute_loss ( [ x . float ( ) for x in train_out ] , targets ) [ 1 ] [ : 3 ] # box, obj, cls
# Run NMS
targets [ : , 2 : ] * = torch . Tensor ( [ width , height , width , height ] ) . to ( device ) # to pixels
lb = [ targets [ targets [ : , 0 ] == i , 1 : ] for i in range ( nb ) ] if save_hybrid else [ ] # for autolabelling
t = time_synchronized ( )
2024-09-15 14:20:39 +08:00
out = non_max_suppression ( out , conf_thres = conf_thres , iou_thres = iou_thres , labels = lb , multi_label = True ) # Does thresholding for class : list of detections, on (n,6) tensor per image [xyxy, conf, cls]
2024-11-04 16:08:35 +08:00
# out = non_max_suppression(out, conf_thres=conf_thres, iou_thres=iou_thres, labels=lb, multi_label=False) # Does thresholding for class : list of detections, on (n,6) tensor per image [xyxy, conf, cls]
2022-07-06 23:23:27 +08:00
t1 + = time_synchronized ( ) - t
# Statistics per image
2024-09-15 14:20:39 +08:00
for si , pred in enumerate ( out ) : # [bbox_coors, objectness_logit, class]
2022-07-06 23:23:27 +08:00
labels = targets [ targets [ : , 0 ] == si , 1 : ]
nl = len ( labels )
tcls = labels [ : , 0 ] . tolist ( ) if nl else [ ] # target class
path = Path ( paths [ si ] )
seen + = 1
if len ( pred ) == 0 :
if nl :
2024-10-15 19:40:02 +08:00
stats . append ( ( torch . zeros ( 0 , niou , dtype = torch . bool ) , torch . Tensor ( ) , torch . Tensor ( ) , tcls ) ) #niou for COCO 0.5:0.05:1
2024-11-04 16:08:35 +08:00
stats_all_large . append ( ( torch . zeros ( 0 , niou , dtype = torch . bool ) , torch . Tensor ( ) , torch . Tensor ( ) , tcls ) )
2024-10-14 15:32:25 +08:00
stats_person_medium . append ( ( torch . zeros ( 0 , niou , dtype = torch . bool ) , torch . Tensor ( ) , torch . Tensor ( ) , tcls ) )
2022-07-06 23:23:27 +08:00
continue
# Predictions
2024-09-15 14:20:39 +08:00
predn = pred . clone ( ) # *xyxy, conf, cls in predn [x y ,w ,h, conf, cls] taking top 300 after NMS
2022-07-06 23:23:27 +08:00
scale_coords ( img [ si ] . shape [ 1 : ] , predn [ : , : 4 ] , shapes [ si ] [ 0 ] , shapes [ si ] [ 1 ] ) # native-space pred
# Append to text file
if save_txt :
gn = torch . tensor ( shapes [ si ] [ 0 ] ) [ [ 1 , 0 , 1 , 0 ] ] # normalization gain whwh
for * xyxy , conf , cls in predn . tolist ( ) :
xywh = ( 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 ( save_dir / ' labels ' / ( path . stem + ' .txt ' ) , ' a ' ) as f :
f . write ( ( ' %g ' * len ( line ) ) . rstrip ( ) % line + ' \n ' )
# W&B logging - Media Panel Plots
if len ( wandb_images ) < log_imgs and wandb_logger . current_epoch > 0 : # Check for test operation
if wandb_logger . current_epoch % wandb_logger . bbox_interval == 0 :
box_data = [ { " position " : { " minX " : xyxy [ 0 ] , " minY " : xyxy [ 1 ] , " maxX " : xyxy [ 2 ] , " maxY " : xyxy [ 3 ] } ,
" class_id " : int ( cls ) ,
" box_caption " : " %s %.3f " % ( names [ cls ] , conf ) ,
" scores " : { " class_score " : conf } ,
" domain " : " pixel " } for * xyxy , conf , cls in pred . tolist ( ) ]
boxes = { " predictions " : { " box_data " : box_data , " class_labels " : names } } # inference-space
wandb_images . append ( wandb_logger . wandb . Image ( img [ si ] , boxes = boxes , caption = path . name ) )
wandb_logger . log_training_progress ( predn , path , names ) if wandb_logger and wandb_logger . wandb_run else None
# 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 = int ( path . stem ) if path . stem . isnumeric ( ) else path . stem
box = xyxy2xywh ( predn [ : , : 4 ] ) # xywh
box [ : , : 2 ] - = box [ : , 2 : ] / 2 # xy center to top-left corner
for p , b in zip ( pred . tolist ( ) , box . tolist ( ) ) :
jdict . append ( { ' image_id ' : image_id ,
' category_id ' : coco91class [ int ( p [ 5 ] ) ] if is_coco else int ( p [ 5 ] ) ,
' bbox ' : [ round ( x , 3 ) for x in b ] ,
' score ' : round ( p [ 4 ] , 5 ) } )
2024-10-27 20:49:26 +08:00
# Assign all predictions as incorrect ; pred takes top 300 predictions conf over 10 ious [0.5:0.95:0.05]
2022-07-06 23:23:27 +08:00
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 ] )
scale_coords ( img [ si ] . shape [ 1 : ] , tbox , shapes [ si ] [ 0 ] , shapes [ si ] [ 1 ] ) # native-space labels
if plots :
2024-11-04 16:08:35 +08:00
confusion_matrix . process_batch ( predn , torch . cat ( ( labels [ : , 0 : 1 ] , tbox ) , 1 ) )
2022-07-06 23:23:27 +08:00
# 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 ( predn [ pi , : 4 ] , tbox [ ti ] ) . max ( 1 ) # best ious, indices
# Append detections
detected_set = set ( )
2024-10-21 20:57:07 +08:00
for j in ( ious > iouv [ 0 ] ) . nonzero ( as_tuple = False ) : # iouv[0]=0.5 IOU for dectetions iouv in general are all 0.5:0.05:.. for COCO
2022-07-06 23:23:27 +08:00
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
2024-10-14 15:32:25 +08:00
# Append statistics (correct, conf_objectness, pcls, tcls) Predicted class is Max-Likelihood among all classes logit and threshol goes over the objectness only
2024-10-21 20:57:07 +08:00
stats . append ( ( correct . cpu ( ) , pred [ : , 4 ] . cpu ( ) , pred [ : , 5 ] . cpu ( ) , tcls ) ) # correct @ IOU=0.5 of pred box with target
2024-10-14 15:32:25 +08:00
if not training or 1 :
2024-09-23 16:23:13 +08:00
# assert len(pred[:, :4]) == 1
x , y , w , h = xyxy2xywh ( pred [ : , : 4 ] ) [ 0 ]
2024-11-06 22:54:53 +08:00
if w * h > hyp [ ' person_size_small_medium_th ' ] and w * h < = hyp [ ' car_size_small_medium_th ' ] :
2024-09-23 16:23:13 +08:00
stats_person_medium . append ( ( correct . cpu ( ) , pred [ : , 4 ] . cpu ( ) , pred [ : , 5 ] . cpu ( ) , tcls ) )
2024-11-06 22:54:53 +08:00
if w * h > hyp [ ' car_size_small_medium_th ' ] :
stats_all_large . append ( ( correct . cpu ( ) , pred [ : , 4 ] . cpu ( ) , pred [ : , 5 ] . cpu ( ) , tcls ) )
2022-07-06 23:23:27 +08:00
2024-10-21 20:57:07 +08:00
# Plot images aa = np.repeat(img[0,:,:,:].cpu().permute(1,2,0).numpy(), 3, axis=2).astype('float32') cv2.imwrite('test/exp40/test_batch88_labels__.jpg', aa*255)
2024-11-13 22:49:31 +08:00
if plots and batch_i > 10 or 1 :
# conf_thresh_plot = 0.1 # the plot threshold the connfidence
2022-07-06 23:23:27 +08:00
f = save_dir / f ' test_batch { batch_i } _labels.jpg ' # labels
Thread ( target = plot_images , args = ( img , targets , paths , f , names ) , daemon = True ) . start ( )
f = save_dir / f ' test_batch { batch_i } _pred.jpg ' # predictions
Thread ( target = plot_images , args = ( img , output_to_target ( out ) , paths , f , names ) , daemon = True ) . start ( )
# Compute statistics
stats = [ np . concatenate ( x , 0 ) for x in zip ( * stats ) ] # to numpy
2024-10-14 15:32:25 +08:00
if not training or 1 :
stats_person_medium = [ np . concatenate ( x , 0 ) for x in zip ( * stats_person_medium ) ] # to numpy
2024-11-04 16:08:35 +08:00
stats_all_large = [ np . concatenate ( x , 0 ) for x in zip ( * stats_all_large ) ] # to numpy
2024-10-14 15:32:25 +08:00
if len ( stats ) and stats [ 0 ] . any ( ) : # P, R @ # max F1 index
2024-10-21 20:57:07 +08:00
p , r , ap , f1 , ap_class = ap_per_class ( * stats , plot = plots , v5_metric = v5_metric , save_dir = save_dir , names = names ) #based on correct @ IOU=0.5 of pred box with target
2024-10-14 15:32:25 +08:00
if not training or 1 :
if bool ( stats_person_medium ) :
2024-11-13 22:49:31 +08:00
p_med , r_med , ap_med , f1_med , ap_class_med = ap_per_class ( * stats_person_medium , plot = plots , v5_metric = v5_metric , save_dir = save_dir , names = names , tag = ' small_objects ' )
2024-10-14 15:32:25 +08:00
ap50_med , ap_med = ap_med [ : , 0 ] , ap_med . mean ( 1 ) # AP@0.5, AP@0.5:0.95
mp_med , mr_med , map50_med , map_med = p_med . mean ( ) , r_med . mean ( ) , ap50_med . mean ( ) , ap_med . mean ( )
nt_med = np . bincount ( stats_person_medium [ 3 ] . astype ( np . int64 ) , minlength = nc ) # number of targets per class
2024-11-04 16:08:35 +08:00
if bool ( stats_all_large ) :
2024-11-13 22:49:31 +08:00
p_large , r_large , ap_large , f1_large , ap_class_large = ap_per_class ( * stats_all_large , plot = plots , v5_metric = v5_metric , save_dir = save_dir , names = names , tag = ' large_objects ' )
2024-11-04 16:08:35 +08:00
ap50_large , ap_large = ap_large [ : , 0 ] , ap_large . mean ( 1 ) # AP@0.5, AP@0.5:0.95
mp_large , mr_large , map50_large , map_large = p_large . mean ( ) , r_large . mean ( ) , ap50_large . mean ( ) , ap_large . mean ( )
nt_large = np . bincount ( stats_all_large [ 3 ] . astype ( np . int64 ) , minlength = nc ) # number of targets per class
2024-09-23 16:23:13 +08:00
2022-07-06 23:23:27 +08:00
ap50 , ap = ap [ : , 0 ] , ap . mean ( 1 ) # AP@0.5, AP@0.5:0.95
mp , mr , map50 , map = p . mean ( ) , r . mean ( ) , ap50 . mean ( ) , ap . mean ( )
2024-09-23 16:23:13 +08:00
2022-07-06 23:23:27 +08:00
nt = np . bincount ( stats [ 3 ] . astype ( np . int64 ) , minlength = nc ) # number of targets per class
else :
nt = torch . zeros ( 1 )
2024-10-14 15:32:25 +08:00
nt_med = torch . zeros ( 1 )
2024-11-04 16:08:35 +08:00
nt_large = torch . zeros ( 1 )
2022-07-06 23:23:27 +08:00
# Print results
pf = ' %20s ' + ' %12i ' * 2 + ' %12.3g ' * 4 # print format
print ( pf % ( ' all ' , seen , nt . sum ( ) , mp , mr , map50 , map ) )
2024-10-14 15:32:25 +08:00
if not training or 1 :
if bool ( stats_person_medium ) :
try :
print ( pf % ( ' all_medium ' , seen , nt_med . sum ( ) , mp_med , mr_med , map50_med , map_med ) )
except Exception as e :
print ( e )
2022-07-06 23:23:27 +08:00
2024-11-04 16:08:35 +08:00
if bool ( stats_all_large ) :
try :
print ( pf % ( ' all_large ' , seen , nt_large . sum ( ) , mp_large , mr_large , map50_large , map_large ) )
except Exception as e :
print ( e )
2024-09-15 14:20:39 +08:00
file_path = os . path . join ( save_dir , ' class_stats.txt ' ) #'Class', 'Images', 'Labels', 'P', 'R', 'mAP@.5', 'mAP@.5:.95'
append_to_txt ( file_path , ' all ' , seen , nt . sum ( ) , mp , mr , map50 , map )
2022-07-06 23:23:27 +08:00
# Print results per class
2024-09-23 16:23:13 +08:00
if 1 or ( verbose or ( nc < 50 and not training ) ) and nc > 1 and len ( stats ) :
2022-07-06 23:23:27 +08:00
for i , c in enumerate ( ap_class ) :
print ( pf % ( names [ c ] , seen , nt [ c ] , p [ i ] , r [ i ] , ap50 [ i ] , ap [ i ] ) )
2024-09-15 14:20:39 +08:00
append_to_txt ( file_path , names [ c ] , seen , nt [ c ] , p [ i ] , r [ i ] , ap50 [ i ] , ap [ i ] )
2024-10-14 15:32:25 +08:00
try :
if bool ( stats_person_medium ) :
for i , c in enumerate ( ap_class_med ) :
print ( pf % ( names [ c ] + ' _med ' , seen , nt_med [ c ] , p_med [ i ] , r_med [ i ] , ap50_med [ i ] , ap_med [ i ] ) )
append_to_txt ( file_path , names [ c ] + ' _med ' , seen , nt_med [ c ] , p_med [ i ] , r_med [ i ] , ap50_med [ i ] , ap_med [ i ] )
except Exception as e :
print ( e )
2022-07-06 23:23:27 +08:00
2024-11-04 16:08:35 +08:00
try :
if bool ( stats_all_large ) :
for i , c in enumerate ( ap_class_large ) :
print ( pf % ( names [ c ] + ' _large ' , seen , nt_large [ c ] , p_large [ i ] , r_large [ i ] , ap50_large [ i ] , ap_large [ i ] ) )
append_to_txt ( file_path , names [ c ] + ' _large ' , seen , nt_large [ c ] , p_large [ i ] , r_large [ i ] , ap50_large [ i ] , ap_large [ i ] )
except Exception as e :
print ( e )
2022-07-06 23:23:27 +08:00
# 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 %g x %g image at batch-size %g ' % t )
# Plots
if plots :
confusion_matrix . plot ( save_dir = save_dir , names = list ( names . values ( ) ) )
if wandb_logger and wandb_logger . wandb :
val_batches = [ wandb_logger . wandb . Image ( str ( f ) , caption = f . name ) for f in sorted ( save_dir . glob ( ' test*.jpg ' ) ) ]
wandb_logger . log ( { " Validation " : val_batches } )
if wandb_images :
wandb_logger . log ( { " Bounding Box Debugger/Images " : wandb_images } )
# Save JSON
2024-08-27 18:58:16 +08:00
if save_json and len ( jdict ) : # @@ HK TODO:
2022-07-06 23:23:27 +08:00
w = Path ( weights [ 0 ] if isinstance ( weights , list ) else weights ) . stem if weights is not None else ' ' # weights
2022-07-11 15:30:56 +08:00
anno_json = ' ./coco/annotations/instances_val2017.json ' # annotations json
2022-07-06 23:23:27 +08:00
pred_json = str ( save_dir / f " { w } _predictions.json " ) # predictions json
print ( ' \n Evaluating pycocotools mAP... saving %s ... ' % pred_json )
with open ( pred_json , ' w ' ) as f :
json . dump ( jdict , f )
try : # https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoEvalDemo.ipynb
from pycocotools . coco import COCO
from pycocotools . cocoeval import COCOeval
anno = COCO ( anno_json ) # init annotations api
pred = anno . loadRes ( pred_json ) # init predictions api
eval = COCOeval ( anno , pred , ' bbox ' )
if is_coco :
eval . params . imgIds = [ int ( Path ( x ) . stem ) for x in dataloader . dataset . img_files ] # image IDs to evaluate
eval . evaluate ( )
eval . accumulate ( )
eval . summarize ( )
map , map50 = eval . stats [ : 2 ] # update results (mAP@0.5:0.95, mAP@0.5)
except Exception as e :
print ( f ' pycocotools unable to run: { e } ' )
# Return results
model . float ( ) # for training
if not training :
s = f " \n { len ( list ( save_dir . glob ( ' labels/*.txt ' ) ) ) } labels saved to { save_dir / ' labels ' } " if save_txt else ' '
print ( f " Results saved to { save_dir } { s } " )
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 = ' yolov7.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 ' )
2024-09-15 14:20:39 +08:00
parser . add_argument ( ' --iou-thres ' , type = float , default = 0.6 , help = ' IOU threshold for NMS ' )
2022-07-06 23:23:27 +08:00
parser . add_argument ( ' --task ' , default = ' val ' , help = ' train, val, test, speed or 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 ( ' --verbose ' , action = ' store_true ' , help = ' report mAP by class ' )
parser . add_argument ( ' --save-txt ' , action = ' store_true ' , help = ' save results to *.txt ' )
parser . add_argument ( ' --save-hybrid ' , action = ' store_true ' , help = ' save label+prediction hybrid results to *.txt ' )
parser . add_argument ( ' --save-conf ' , action = ' store_true ' , help = ' save confidences in --save-txt labels ' )
parser . add_argument ( ' --save-json ' , action = ' store_true ' , help = ' save a cocoapi-compatible JSON results file ' )
parser . add_argument ( ' --project ' , default = ' runs/test ' , help = ' save to project/name ' )
parser . add_argument ( ' --name ' , default = ' exp ' , help = ' save to project/name ' )
parser . add_argument ( ' --exist-ok ' , action = ' store_true ' , help = ' existing project/name ok, do not increment ' )
2022-07-09 07:26:32 +08:00
parser . add_argument ( ' --no-trace ' , action = ' store_true ' , help = ' don`t trace model ' )
2022-09-17 02:14:01 +08:00
parser . add_argument ( ' --v5-metric ' , action = ' store_true ' , help = ' assume maximum recall as 1.0 in AP calculation ' )
2024-09-15 14:20:39 +08:00
parser . add_argument ( ' --norm-type ' , type = str , default = ' standardization ' ,
choices = [ ' standardization ' , ' single_image_0_to_1 ' , ' single_image_mean_std ' , ' single_image_percentile_0_255 ' ,
' single_image_percentile_0_1 ' , ' remove+global_outlier_0_1 ' ] ,
help = ' Normalization approach ' )
2024-09-23 16:23:13 +08:00
parser . add_argument ( ' --no-tir-signal ' , action = ' store_true ' , help = ' ' )
parser . add_argument ( ' --tir-channel-expansion ' , action = ' store_true ' , help = ' drc_per_ch_percentile ' )
2024-09-15 14:20:39 +08:00
parser . add_argument ( ' --input-channels ' , type = int , default = 3 , help = ' ' )
2024-10-14 15:32:25 +08:00
parser . add_argument ( ' --save-path ' , default = ' ' , help = ' save to project/name ' )
2022-07-06 23:23:27 +08:00
opt = parser . parse_args ( )
2024-09-23 16:23:13 +08:00
if opt . tir_channel_expansion : # operates over 3 channels
opt . input_channels = 3
if opt . tir_channel_expansion and opt . norm_type != ' single_image_percentile_0_1 ' : # operates over 3 channels
print ( ' Not a good combination ' )
2022-07-06 23:23:27 +08:00
opt . save_json | = opt . data . endswith ( ' coco.yaml ' )
opt . data = check_file ( opt . data ) # check file
print ( opt )
#check_requirements()
2024-11-04 16:08:35 +08:00
hyp = dict ( )
2022-07-06 23:23:27 +08:00
if opt . task in ( ' train ' , ' 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 ,
save_txt = opt . save_txt | opt . save_hybrid ,
save_hybrid = opt . save_hybrid ,
save_conf = opt . save_conf ,
2022-07-09 07:26:32 +08:00
trace = not opt . no_trace ,
2024-11-04 16:08:35 +08:00
v5_metric = opt . v5_metric ,
hyp = hyp )
2022-07-06 23:23:27 +08:00
elif opt . task == ' speed ' : # speed benchmarks
for w in opt . weights :
2022-09-17 02:14:01 +08:00
test ( opt . data , w , opt . batch_size , opt . img_size , 0.25 , 0.45 , save_json = False , plots = False , v5_metric = opt . v5_metric )
2022-07-06 23:23:27 +08:00
elif opt . task == ' study ' : # run over a range of settings and save/plot
# python test.py --task study --data coco.yaml --iou 0.65 --weights yolov7.pt
x = list ( range ( 256 , 1536 + 128 , 128 ) ) # x axis (image sizes)
for w in opt . weights :
f = f ' study_ { Path ( opt . data ) . stem } _ { Path ( w ) . stem } .txt ' # filename to save to
y = [ ] # y axis
for i in x : # img-size
print ( f ' \n Running { f } point { i } ... ' )
r , _ , t = test ( opt . data , w , opt . batch_size , i , opt . conf_thres , opt . iou_thres , opt . save_json ,
2022-09-17 02:14:01 +08:00
plots = False , v5_metric = opt . v5_metric )
2022-07-06 23:23:27 +08:00
y . append ( r + t ) # results and times
np . savetxt ( f , y , fmt = ' %10.4g ' ) # save
os . system ( ' zip -r study.zip study_*.txt ' )
plot_study_txt ( x = x ) # plot
2024-09-15 14:20:39 +08:00
"""
2024-09-23 16:23:13 +08:00
- - weights . / yolov7 / yolov7 . pt - - device 0 - - batch - size 16 - - data data / coco_2_tir . yaml - - img - size 640 - - conf 0.6 - - verbose - - save - txt - - save - hybrid - - norm - type single_image_percentile_0_1
test based on RGB coco model
- - weights . / yolov7 / yolov7 . pt - - device 0 - - batch - size 64 - - data data / coco_2_tir . yaml - - img - size 640 - - conf 0.25 - - verbose - - save - txt - - norm - type single_image_percentile_0_1 - - project test - - task train
- - weights . / yolov7 / yolov7 . pt - - device 0 - - batch - size 64 - - data data / tir_od . yaml - - img - size 640 - - conf 0.25 - - verbose - - save - txt - - norm - type single_image_percentile_0_1 - - project test - - task val
2024-10-14 15:32:25 +08:00
# Using pretrained model
- - weights / mnt / Data / hanoch / runs / train / yolov7434 / weights / epoch_099 . pt - - device 0 - - batch - size 4 - - data data / tir_od_test_set . yaml - - img - size 640 - - conf 0.25 - - verbose - - norm - type single_image_percentile_0_1 - - project test - - task test
2024-10-21 20:57:07 +08:00
#vbased on 7555 mAP=82.3
- - weights / mnt / Data / hanoch / runs / train / yolov7563 / weights / best . pt - - device 0 - - batch - size 16 - - data data / tir_od_test_set . yaml - - img - size 640 - - conf 0.02 - - verbose - - norm - type single_image_percentile_0_1 - - input - channels 1 - - project test - - task test - - iou - thres 0.4
/ home / hanoch / projects / tir_od / runs / train / yolov7563 / weights
2024-10-27 20:49:26 +08:00
- - weights / mnt / Data / hanoch / runs / train / yolov7575 / weights / best . pt - - device 0 - - batch - size 16 - - data data / tir_od_test_set . yaml - - img - size 640 - - conf 0.001 - - verbose - - norm - type single_image_percentile_0_1 - - input - channels 1 - - project test - - task test - - iou - thres 0.6
2024-10-30 21:43:20 +08:00
- - weights / home / hanoch / projects / tir_od / runs / gpu02 / yolov74 / weights - - device 0 - - batch - size 16 - - data data / tir_od_test_set . yaml - - img - size 640 - - conf 0.001 - - verbose - - norm - type single_image_percentile_0_1 - - input - channels 1 - - project test - - task test - - iou - thres 0.6
2024-09-15 14:20:39 +08:00
"""