Spaces:
Runtime error
Runtime error
| # Copyright (c) OpenMMLab. All rights reserved. | |
| # Copyright (c) https://github.com/mcordts/cityscapesScripts | |
| # A wrapper of `cityscapesscripts` which supports loading groundtruth | |
| # image from `backend_args`. | |
| import json | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from typing import Optional, Union | |
| import mmcv | |
| import numpy as np | |
| from mmengine.fileio import get | |
| try: | |
| import cityscapesscripts.evaluation.evalInstanceLevelSemanticLabeling as CSEval # noqa: E501 | |
| from cityscapesscripts.evaluation.evalInstanceLevelSemanticLabeling import \ | |
| CArgs # noqa: E501 | |
| from cityscapesscripts.evaluation.instance import Instance | |
| from cityscapesscripts.helpers.csHelpers import (id2label, labels, | |
| writeDict2JSON) | |
| HAS_CITYSCAPESAPI = True | |
| except ImportError: | |
| CArgs = object | |
| HAS_CITYSCAPESAPI = False | |
| def evaluateImgLists(prediction_list: list, | |
| groundtruth_list: list, | |
| args: CArgs, | |
| backend_args: Optional[dict] = None, | |
| dump_matches: bool = False) -> dict: | |
| """A wrapper of obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.evaluateImgLists``. Support loading | |
| groundtruth image from file backend. | |
| Args: | |
| prediction_list (list): A list of prediction txt file. | |
| groundtruth_list (list): A list of groundtruth image file. | |
| args (CArgs): A global object setting in | |
| obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling`` | |
| backend_args (dict, optional): Arguments to instantiate the | |
| preifx of uri corresponding backend. Defaults to None. | |
| dump_matches (bool): whether dump matches.json. Defaults to False. | |
| Returns: | |
| dict: The computed metric. | |
| """ | |
| if not HAS_CITYSCAPESAPI: | |
| raise RuntimeError('Failed to import `cityscapesscripts`.' | |
| 'Please try to install official ' | |
| 'cityscapesscripts by ' | |
| '"pip install cityscapesscripts"') | |
| # determine labels of interest | |
| CSEval.setInstanceLabels(args) | |
| # get dictionary of all ground truth instances | |
| gt_instances = getGtInstances( | |
| groundtruth_list, args, backend_args=backend_args) | |
| # match predictions and ground truth | |
| matches = matchGtWithPreds(prediction_list, groundtruth_list, gt_instances, | |
| args, backend_args) | |
| if dump_matches: | |
| CSEval.writeDict2JSON(matches, 'matches.json') | |
| # evaluate matches | |
| apScores = CSEval.evaluateMatches(matches, args) | |
| # averages | |
| avgDict = CSEval.computeAverages(apScores, args) | |
| # result dict | |
| resDict = CSEval.prepareJSONDataForResults(avgDict, apScores, args) | |
| if args.JSONOutput: | |
| # create output folder if necessary | |
| path = os.path.dirname(args.exportFile) | |
| CSEval.ensurePath(path) | |
| # Write APs to JSON | |
| CSEval.writeDict2JSON(resDict, args.exportFile) | |
| CSEval.printResults(avgDict, args) | |
| return resDict | |
| def matchGtWithPreds(prediction_list: list, | |
| groundtruth_list: list, | |
| gt_instances: dict, | |
| args: CArgs, | |
| backend_args=None): | |
| """A wrapper of obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.matchGtWithPreds``. Support loading | |
| groundtruth image from file backend. | |
| Args: | |
| prediction_list (list): A list of prediction txt file. | |
| groundtruth_list (list): A list of groundtruth image file. | |
| gt_instances (dict): Groundtruth dict. | |
| args (CArgs): A global object setting in | |
| obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling`` | |
| backend_args (dict, optional): Arguments to instantiate the | |
| preifx of uri corresponding backend. Defaults to None. | |
| Returns: | |
| dict: The processed prediction and groundtruth result. | |
| """ | |
| if not HAS_CITYSCAPESAPI: | |
| raise RuntimeError('Failed to import `cityscapesscripts`.' | |
| 'Please try to install official ' | |
| 'cityscapesscripts by ' | |
| '"pip install cityscapesscripts"') | |
| matches: dict = dict() | |
| if not args.quiet: | |
| print(f'Matching {len(prediction_list)} pairs of images...') | |
| count = 0 | |
| for (pred, gt) in zip(prediction_list, groundtruth_list): | |
| # Read input files | |
| gt_image = readGTImage(gt, backend_args) | |
| pred_info = readPredInfo(pred) | |
| # Get and filter ground truth instances | |
| unfiltered_instances = gt_instances[gt] | |
| cur_gt_instances_orig = CSEval.filterGtInstances( | |
| unfiltered_instances, args) | |
| # Try to assign all predictions | |
| (cur_gt_instances, | |
| cur_pred_instances) = CSEval.assignGt2Preds(cur_gt_instances_orig, | |
| gt_image, pred_info, args) | |
| # append to global dict | |
| matches[gt] = {} | |
| matches[gt]['groundTruth'] = cur_gt_instances | |
| matches[gt]['prediction'] = cur_pred_instances | |
| count += 1 | |
| if not args.quiet: | |
| print(f'\rImages Processed: {count}', end=' ') | |
| sys.stdout.flush() | |
| if not args.quiet: | |
| print('') | |
| return matches | |
| def readGTImage(image_file: Union[str, Path], | |
| backend_args: Optional[dict] = None) -> np.ndarray: | |
| """Read an image from path. | |
| Same as obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.readGTImage``, but support loading | |
| groundtruth image from file backend. | |
| Args: | |
| image_file (str or Path): Either a str or pathlib.Path. | |
| backend_args (dict, optional): Instantiates the corresponding file | |
| backend. It may contain `backend` key to specify the file | |
| backend. If it contains, the file backend corresponding to this | |
| value will be used and initialized with the remaining values, | |
| otherwise the corresponding file backend will be selected | |
| based on the prefix of the file path. Defaults to None. | |
| Returns: | |
| np.ndarray: The groundtruth image. | |
| """ | |
| img_bytes = get(image_file, backend_args=backend_args) | |
| img = mmcv.imfrombytes(img_bytes, flag='unchanged', backend='pillow') | |
| return img | |
| def readPredInfo(prediction_file: str) -> dict: | |
| """A wrapper of obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.readPredInfo``. | |
| Args: | |
| prediction_file (str): The prediction txt file. | |
| Returns: | |
| dict: The processed prediction results. | |
| """ | |
| if not HAS_CITYSCAPESAPI: | |
| raise RuntimeError('Failed to import `cityscapesscripts`.' | |
| 'Please try to install official ' | |
| 'cityscapesscripts by ' | |
| '"pip install cityscapesscripts"') | |
| printError = CSEval.printError | |
| predInfo = {} | |
| if (not os.path.isfile(prediction_file)): | |
| printError(f"Infofile '{prediction_file}' " | |
| 'for the predictions not found.') | |
| with open(prediction_file) as f: | |
| for line in f: | |
| splittedLine = line.split(' ') | |
| if len(splittedLine) != 3: | |
| printError('Invalid prediction file. Expected content: ' | |
| 'relPathPrediction1 labelIDPrediction1 ' | |
| 'confidencePrediction1') | |
| if os.path.isabs(splittedLine[0]): | |
| printError('Invalid prediction file. First entry in each ' | |
| 'line must be a relative path.') | |
| filename = os.path.join( | |
| os.path.dirname(prediction_file), splittedLine[0]) | |
| imageInfo = {} | |
| imageInfo['labelID'] = int(float(splittedLine[1])) | |
| imageInfo['conf'] = float(splittedLine[2]) # type: ignore | |
| predInfo[filename] = imageInfo | |
| return predInfo | |
| def getGtInstances(groundtruth_list: list, | |
| args: CArgs, | |
| backend_args: Optional[dict] = None) -> dict: | |
| """A wrapper of obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.getGtInstances``. Support loading | |
| groundtruth image from file backend. | |
| Args: | |
| groundtruth_list (list): A list of groundtruth image file. | |
| args (CArgs): A global object setting in | |
| obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling`` | |
| backend_args (dict, optional): Arguments to instantiate the | |
| preifx of uri corresponding backend. Defaults to None. | |
| Returns: | |
| dict: The computed metric. | |
| """ | |
| if not HAS_CITYSCAPESAPI: | |
| raise RuntimeError('Failed to import `cityscapesscripts`.' | |
| 'Please try to install official ' | |
| 'cityscapesscripts by ' | |
| '"pip install cityscapesscripts"') | |
| # if there is a global statistics json, then load it | |
| if (os.path.isfile(args.gtInstancesFile)): | |
| if not args.quiet: | |
| print('Loading ground truth instances from JSON.') | |
| with open(args.gtInstancesFile) as json_file: | |
| gt_instances = json.load(json_file) | |
| # otherwise create it | |
| else: | |
| if (not args.quiet): | |
| print('Creating ground truth instances from png files.') | |
| gt_instances = instances2dict( | |
| groundtruth_list, args, backend_args=backend_args) | |
| writeDict2JSON(gt_instances, args.gtInstancesFile) | |
| return gt_instances | |
| def instances2dict(image_list: list, | |
| args: CArgs, | |
| backend_args: Optional[dict] = None) -> dict: | |
| """A wrapper of obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling.instances2dict``. Support loading | |
| groundtruth image from file backend. | |
| Args: | |
| image_list (list): A list of image file. | |
| args (CArgs): A global object setting in | |
| obj:``cityscapesscripts.evaluation. | |
| evalInstanceLevelSemanticLabeling`` | |
| backend_args (dict, optional): Arguments to instantiate the | |
| preifx of uri corresponding backend. Defaults to None. | |
| Returns: | |
| dict: The processed groundtruth results. | |
| """ | |
| if not HAS_CITYSCAPESAPI: | |
| raise RuntimeError('Failed to import `cityscapesscripts`.' | |
| 'Please try to install official ' | |
| 'cityscapesscripts by ' | |
| '"pip install cityscapesscripts"') | |
| imgCount = 0 | |
| instanceDict = {} | |
| if not isinstance(image_list, list): | |
| image_list = [image_list] | |
| if not args.quiet: | |
| print(f'Processing {len(image_list)} images...') | |
| for image_name in image_list: | |
| # Load image | |
| img_bytes = get(image_name, backend_args=backend_args) | |
| imgNp = mmcv.imfrombytes(img_bytes, flag='unchanged', backend='pillow') | |
| # Initialize label categories | |
| instances: dict = {} | |
| for label in labels: | |
| instances[label.name] = [] | |
| # Loop through all instance ids in instance image | |
| for instanceId in np.unique(imgNp): | |
| instanceObj = Instance(imgNp, instanceId) | |
| instances[id2label[instanceObj.labelID].name].append( | |
| instanceObj.toDict()) | |
| instanceDict[image_name] = instances | |
| imgCount += 1 | |
| if not args.quiet: | |
| print(f'\rImages Processed: {imgCount}', end=' ') | |
| sys.stdout.flush() | |
| return instanceDict | |