| | |
| | |
| | |
| | |
| | |
| |
|
| | """ |
| | COCO-Style Evaluations |
| | |
| | put images here datasets/your_project_name/val_set_name/*.jpg |
| | put annotations here datasets/your_project_name/annotations/instances_{val_set_name}.json |
| | put weights here /path/to/your/weights/*.pth |
| | change compound_coef |
| | |
| | """ |
| |
|
| | import json |
| | import os |
| | import numpy as np |
| |
|
| | import argparse |
| | import torch |
| | from tqdm import tqdm |
| | from pycocotools.coco import COCO |
| | from pycocotools.cocoeval import COCOeval |
| | from torch.utils.data import DataLoader |
| | import torchvision |
| | import torchvision.transforms as transforms |
| | import time |
| |
|
| | from models import mnv2_SSDlite |
| | from library.ssd import conv_model_fptunc2fpt, conv_model_fpt2qat, conv_model_qat2hw, collate_fn, PredsPostProcess, round_floats |
| | from dataloader import CocoDetection, input_fxpt_normalize |
| |
|
| | |
| |
|
| | ap = argparse.ArgumentParser() |
| | ap.add_argument('-m', '--mode', type=str, default='qat', help='Mode of the model, allowed modes: fpt_unc, fpt, qat') |
| | ap.add_argument('--nms_threshold', type=float, default=0.5, help='non max supression threshold') |
| | ap.add_argument('--conf_threshold', type=float, default=0.5, help='confidence treshold, predictions below this level will be discarded') |
| | ap.add_argument('-dp', '--data_path', type=str, default=None, help='/path/to/images') |
| | ap.add_argument('-ap', '--json_path', type=str, default=None, help='/path/to/annotations.json') |
| | ap.add_argument('-wp', '--weights_path', type=str, default=None, help='/path/to/weights') |
| |
|
| | args = ap.parse_args() |
| |
|
| | mode = args.mode |
| | nms_threshold = args.nms_threshold |
| | conf_threshold = args.conf_threshold |
| | data_path = args.data_path |
| | json_path = args.json_path |
| | weights_path = args.weights_path |
| |
|
| | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| |
|
| | def evaluate_coco(model, DATA_PATH, JSON_PATH , nmsIoUTreshold = 0.5, PredMinConfTreshold = 0.5, HW_mode = False): |
| | |
| | if HW_mode: |
| | act_8b_mode = True |
| | else: |
| | act_8b_mode = False |
| |
|
| | transform = transforms.Compose([transforms.ToTensor(), input_fxpt_normalize(act_8b_mode=act_8b_mode)]) |
| | targetFileName = 'resized.json' |
| | dataset = CocoDetection(root=DATA_PATH, annFile=JSON_PATH, transform=transform, scaleImgforCrop= None) |
| |
|
| | dataset.createResizedAnnotJson(targetFileName=targetFileName) |
| | resizedFilePath = os.path.join(os.path.split(JSON_PATH)[0],targetFileName) |
| | cocoGt=COCO(resizedFilePath) |
| | os.remove(resizedFilePath) |
| |
|
| | seq_sampler = torch.utils.data.SequentialSampler(dataset) |
| | data_loader = DataLoader(dataset, |
| | sampler=seq_sampler, |
| | batch_size=1, |
| | collate_fn=collate_fn, |
| | drop_last=False) |
| | print(f"Dataset Length: {len(dataset)}, Number of Batches: {len(data_loader)}") |
| | |
| | ANCHORS_HEAD1 = [(11.76, 28.97), |
| | (20.98, 52.03), |
| | (29.91, 77.24), |
| | (38.97, 106.59)] |
| |
|
| | ANCHORS_HEAD2 = [(52.25, 144.77), |
| | (65.86, 193.05), |
| | (96.37, 254.09), |
| | (100.91, 109.82), |
| | (140, 350)] |
| | |
| | predsPostProcess = PredsPostProcess(512, ANCHORS_HEAD1, ANCHORS_HEAD2) |
| |
|
| | |
| | dataDictList =[] |
| | imgIDS = [] |
| | for i, data in enumerate(tqdm(data_loader)): |
| | imageBatch, targetBatch , idxBatch = data |
| |
|
| | imageStack = torch.stack(imageBatch).detach().to(device) |
| | imageStack.requires_grad_(True) |
| | predBatch = model(imageStack) |
| | |
| | if HW_mode: |
| | BBs1 = predBatch[0].detach() / 128.0 |
| | CFs1 = predBatch[1].detach() / 128.0 |
| | BBs2 = predBatch[2].detach() / 128.0 |
| | CFs2 = predBatch[3].detach() / 128.0 |
| | else: |
| | BBs1 = predBatch[0].detach() |
| | CFs1 = predBatch[1].detach() |
| | BBs2 = predBatch[2].detach() |
| | CFs2 = predBatch[3].detach() |
| |
|
| | for imgNum in range(imageStack.shape[0]): |
| | img = imageStack[imgNum,:,:,:] |
| | target = targetBatch[imgNum] |
| | image_id = int(idxBatch[imgNum]) |
| | imgIDS.append(image_id) |
| |
|
| | pred = (BBs1[imgNum,:,:,:].unsqueeze(0), CFs1[imgNum,:,:,:].unsqueeze(0), |
| | BBs2[imgNum,:,:,:].unsqueeze(0), CFs2[imgNum,:,:,:].unsqueeze(0)) |
| |
|
| | boxes, confidences = predsPostProcess.getPredsInOriginal(pred) |
| |
|
| | nms_picks = torchvision.ops.nms(boxes, confidences, nmsIoUTreshold) |
| | boxes_to_draw = boxes[nms_picks] |
| | confs_to_draw = confidences[nms_picks] |
| | confMask = (confs_to_draw > PredMinConfTreshold) |
| |
|
| | |
| | if (confMask.any()): |
| |
|
| | |
| | bbox = boxes_to_draw[confMask] |
| | scores = confs_to_draw[confMask] |
| | |
| | bbox[:,2] = bbox[:,2] - bbox[:,0] |
| | bbox[:,3] = bbox[:,3] - bbox[:,1] |
| | |
| |
|
| | bbox = bbox.tolist() |
| | score = scores.tolist() |
| | category_id = np.ones_like(score,dtype=int).tolist() |
| |
|
| | for j in range(len(bbox)): |
| | box = {"image_id":image_id, "category_id":category_id[j], "bbox":bbox[j],"score":score[j]} |
| | dataDictList.append(round_floats(box)) |
| |
|
| | if (len(dataDictList)): |
| | |
| | cocoDT = json.dumps(dataDictList) |
| |
|
| | |
| | with open('cocoDT.json', 'w') as outfile: |
| | outfile.write(cocoDT) |
| |
|
| | |
| | cocoDt=cocoGt.loadRes('cocoDT.json') |
| | os.remove("cocoDT.json") |
| |
|
| | |
| | annType = 'bbox' |
| | cocoEval = COCOeval(cocoGt,cocoDt,annType) |
| | cocoEval.params.catIds = 1 |
| | cocoEval.params.imgIds = imgIDS |
| | cocoEval.evaluate() |
| | cocoEval.accumulate() |
| | |
| | print('') |
| | cocoEval.summarize() |
| | else: |
| | raise Exception('the model does not provide any valid output, check model architecture and the data input') |
| |
|
| |
|
| | if __name__ == '__main__': |
| | model = mnv2_SSDlite() |
| | |
| | layer_bits_dictionary = {} |
| | layer_bits_dictionary['conv1' ] = 8; |
| | layer_bits_dictionary['epw_conv2' ] = 8; |
| | layer_bits_dictionary['dw_conv2' ] = 8; |
| | layer_bits_dictionary['ppw_conv2' ] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv3' ] = 8; |
| | layer_bits_dictionary['dw_conv3' ] = 8; |
| | layer_bits_dictionary['ppw_conv3' ] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv4' ] = 8; |
| | layer_bits_dictionary['dw_conv4' ] = 8; |
| | layer_bits_dictionary['ppw_conv4' ] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv5'] = 8; |
| | layer_bits_dictionary['dw_conv5'] = 8; |
| | layer_bits_dictionary['ppw_conv5'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv6'] = 8; |
| | layer_bits_dictionary['dw_conv6'] = 8; |
| | layer_bits_dictionary['ppw_conv6'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv7'] = 8; |
| | layer_bits_dictionary['dw_conv7'] = 8; |
| | layer_bits_dictionary['ppw_conv7'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv8'] = 8; |
| | layer_bits_dictionary['dw_conv8'] = 8; |
| | layer_bits_dictionary['ppw_conv8'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv9'] = 8; |
| | layer_bits_dictionary['dw_conv9'] = 8; |
| | layer_bits_dictionary['ppw_conv9'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv10'] = 8; |
| | layer_bits_dictionary['dw_conv10'] = 8; |
| | layer_bits_dictionary['ppw_conv10'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv11'] = 8; |
| | layer_bits_dictionary['dw_conv11'] = 8; |
| | layer_bits_dictionary['ppw_conv11'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv12'] = 8; |
| | layer_bits_dictionary['dw_conv12'] = 8; |
| | layer_bits_dictionary['ppw_conv12'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv13'] = 8; |
| | layer_bits_dictionary['dw_conv13'] = 8; |
| | layer_bits_dictionary['ppw_conv13'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv14'] = 8; |
| | layer_bits_dictionary['dw_conv14'] = 8; |
| | layer_bits_dictionary['ppw_conv14'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv15'] = 8; |
| | layer_bits_dictionary['dw_conv15'] = 8; |
| | layer_bits_dictionary['ppw_conv15'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv16'] = 8; |
| | layer_bits_dictionary['dw_conv16'] = 8; |
| | layer_bits_dictionary['ppw_conv16'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv17'] = 8; |
| | layer_bits_dictionary['dw_conv17'] = 8; |
| | layer_bits_dictionary['ppw_conv17'] = 8; |
| |
|
| | layer_bits_dictionary['epw_conv18'] = 8; |
| | layer_bits_dictionary['dw_conv18'] = 8; |
| | layer_bits_dictionary['ppw_conv18'] = 8; |
| |
|
| | layer_bits_dictionary['head1_dw_classification'] = 8; |
| | layer_bits_dictionary['head1_pw_classification'] = 8; |
| | layer_bits_dictionary['head1_dw_regression'] = 8; |
| | layer_bits_dictionary['head1_pw_regression'] = 8; |
| |
|
| | layer_bits_dictionary['head2_dw_classification'] = 8; |
| | layer_bits_dictionary['head2_pw_classification'] = 8; |
| | layer_bits_dictionary['head2_dw_regression'] = 8; |
| | layer_bits_dictionary['head2_pw_regression'] = 8; |
| |
|
| | |
| | HW_mode = False |
| | if mode == 'fpt_unc': |
| | model.to(device) |
| | |
| | elif mode == 'fpt': |
| | model = conv_model_fptunc2fpt(model) |
| | model.to(device) |
| | |
| | elif mode == 'qat': |
| | model = conv_model_fptunc2fpt(model) |
| | model.to(device) |
| | model = conv_model_fpt2qat(model, layer_bits_dictionary) |
| | model.to(device) |
| | |
| | elif mode == 'hw': |
| | HW_mode = True |
| | model = conv_model_fptunc2fpt(model) |
| | model.to(device) |
| | model = conv_model_fpt2qat(model, layer_bits_dictionary) |
| | model.to(device) |
| | model = conv_model_qat2hw(model) |
| | model.to(device) |
| |
|
| | else: |
| | raise Exception('Invalid model mode is selected, select from: fpt_unc, fpt, qat, hw') |
| |
|
| |
|
| | weights = torch.load(weights_path, map_location=torch.device('cpu')) |
| | model.load_state_dict(weights['state_dict'], strict=True) |
| |
|
| | model.requires_grad_(False) |
| | model.eval() |
| | |
| | if mode == 'qat' or mode == 'hw': |
| | print(''*5) |
| | print('*'*120) |
| | print('qat or hardware mode is selected, please make sure you configured layer_bits_dictionary in "coco_eval.py" accordingly!!!') |
| | print('*'*120) |
| | print('') |
| | time.sleep(5) |
| |
|
| | evaluate_coco(model, DATA_PATH=data_path, JSON_PATH=json_path , nmsIoUTreshold=nms_threshold, |
| | PredMinConfTreshold=conf_threshold, HW_mode = HW_mode) |