def getDataset(self, path: str): if not os.path.isdir(path): raise FileNotFoundError( "Could not find Y4Signs dataset on path: " + path) images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} for data_path in os.listdir(path): if 'png' in data_path: image_path = os.path.join(path, data_path) images.append(image_path) annot_path = os.path.join(path, data_path[:-len('png')] + 'pkl') annots = None with open(annot_path, 'rb') as annot_file: annots = pickle.load(annot_file) annotations[image_path] = annots classes = None with open(os.path.join(path, 'classes.pkl'), 'rb') as annot_file: classes = pickle.load(annot_file) return Dataset(self.dataset_name, images, classes, annotations)
def _lisa(path: str) -> Dataset: # pylint:disable=too-many-locals,too-many-branches images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} day_train_path = os.path.join(path, "dayTrain") if not os.path.isdir(day_train_path): raise FileNotFoundError("Could not find `dayTrain` in LISA dataset.") for file_name in os.listdir(day_train_path): if not file_name.startswith("dayClip"): continue clip_path = os.path.join(day_train_path, file_name) frames_path = os.path.join(clip_path, "frames") annotations_path = os.path.join(clip_path, "frameAnnotationsBOX.csv") if not os.path.exists(frames_path): raise FileNotFoundError(f"Could not find frames folder {frames_path}.") if not os.path.exists(annotations_path): raise FileNotFoundError(f"Could not find annotations file {annotations_path}") # Read annotations with open(annotations_path, "r") as annotations_file: reader = csv.reader(annotations_file, delimiter=";") for i, row in enumerate(reader): # Skip the first row, it is just headers if i == 0: continue image_name = row[0].split("/")[-1] image_path = os.path.join(frames_path, image_name) detection_class = row[1] # Calculate the position and dimensions of the bounding box x_min = int(row[2]) # x-coordinate of top left corner y_min = int(row[3]) # y-coordinate of top left corner x_max = int(row[4]) # x-coordinate of bottom right corner y_max = int(row[5]) # y-coordinate of bottom right corner # Get the class index if it has already been registered # otherwise register it and select the index try: class_index = classes.index(detection_class) except ValueError: class_index = len(classes) classes.append(detection_class) # Package the detection images.append(image_path) if image_path not in annotations: annotations[image_path] = [] annotations[image_path].append( Object2D(Bounds2D(x_min, y_min, x_max - x_min, y_max - y_min), class_index)) return Dataset(LIGHT_DATASET_NAME, images, classes, annotations)
def _Y4Signs(path: str) -> Dataset: if not os.path.isdir(path): raise FileNotFoundError("Could not find Y4Signs dataset on this path.") images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} # list of classes [str] in set01/obj.names classes = open(os.path.join(path, "set01", "obj.names")).read().splitlines() for set_ in os.listdir(path): if os.path.isdir(os.path.join(path, set_, "train.txt")): raise FileNotFoundError("train.txt does not exist in " + set_) f = open(os.path.join(path, set_, "train.txt")) #list of all absolute paths from train.txt. extra /data out for rel_image_path in f.read().split(): # absolute image path to the image. abs_image_path = os.path.join(path, set_, rel_image_path[4:]) # append the image path to list of images images.append(abs_image_path) # annotations file for corresponding image annotation_file_path = abs_image_path[:-4] + ".txt" annotation_file = open(annotation_file_path) temp_annotations = [] # read the annotations file and loop through each line. for bounding_box in annotation_file.read().splitlines(): # split each line with spaces to get the [class, x1, y1, x2, y2] annotation_arr = bounding_box.strip().split(" ") # check if legal if not len(annotation_arr) == 5: raise InvalidBoundingBoxError(annotation_file_path) # Construct and append an Object2D object temp_annotations.append( Object2D( Bounds2D( float(annotation_arr[1]), float(annotation_arr[2]), float(annotation_arr[3]), float(annotation_arr[4]), ), int(annotation_arr[0]))) # exit for loop and added (abs_image_path, temp_annotation: list) key value pair. annotations[abs_image_path] = temp_annotations return Dataset(DATASET_NAME, images, classes, annotations)
def _jaad_dataset(path: str) -> Dataset: # pylint:disable=too-many-locals, too-many-branches images: Dataset.Images = [] classes: Dataset.Classes = ['pedestrian', 'ped', 'people'] annotations: Dataset.Annotations = {} data_params = { 'fstride': 1, 'sample_type': 'all', 'subset': 'all_videos', # 'high_visibility' (high + low res, high vis), 'default' (high res, high vis only) 'data_split_type': 'default', 'height_rng': [0, float('inf')], 'squarify_ratio': 0 } jaad = JAAD(data_path=path) jaad_anns = jaad.generate_database() # get all video ids train_ids, _ = jaad.get_data_ids('train', data_params) val_ids, _ = jaad.get_data_ids('val', data_params) test_ids, _ = jaad.get_data_ids('test', data_params) video_ids = train_ids + val_ids + test_ids for vid in video_ids: for pid in jaad_anns[vid]['ped_annotations']: imgs = [ os.path.join(jaad.jaad_path, 'images', vid, '{:05d}.png'.format(f)) for f in jaad_anns[vid]['ped_annotations'][pid]['frames'] ] boxes = jaad_anns[vid]['ped_annotations'][pid]['bbox'] for box, img in zip(boxes, imgs): bounds = Bounds2D(box[0], box[1], box[2] - box[0], box[3] - box[1]) if 'pedestrian' in jaad_anns[vid]['ped_annotations'][pid][ 'old_id']: class_index = classes.index('pedestrian') elif 'people' in jaad_anns[vid]['ped_annotations'][pid][ 'old_id']: class_index = classes.index('people') else: class_index = classes.index('ped') if img not in annotations: images.append(img) annotations[img] = [Object2D(bounds, class_index)] else: annotations[img].append(Object2D(bounds, class_index)) return Dataset(DATASET_NAME, images, classes, annotations)
def _lyftperception( path: str = '/home/lns/.lns-training/resources/data/LyftPerception/', datatype: str = 'train') -> Dataset: # noqa images: Dataset.Images = [] classes: Dataset.Classes = [ 'car', 'pedestrian', 'animal', 'other_vehicle', 'bus', 'motorcycle', 'truck', 'emergency_vehicle', 'bicycle' ] annotations: Dataset.Annotations = {} lyft = LyftDataset( data_path= path, # '/home/lns/.lns-training/resources/data/LyftPerception/train', # path, json_path=os.path.join(path, 'data'), # datatype + '_data'), verbose=True, map_resolution=0.1) # '/home/lns/.lns-training/resources/data/LyftPerception/train/train_data', for sample in lyft.sample: cam_token = sample['data']['CAM_FRONT'] # Returns the data path as well as all annotations related to that sample_data. # Note that the boxes are transformed into the current sensor's coordinate frame. data_path, boxes, camera_intrinsic = lyft.get_sample_data(cam_token) images.append(str(data_path)) annotations[str(data_path)] = [] for box in boxes: img_corners = view_points(box.corners(), camera_intrinsic, normalize=True)[:2, :] # Take an outer rect of the 3d projection xmin = img_corners[0].min( ) if img_corners[0].min() >= 0 else 0 # 1224x1024 xmax = img_corners[0].max( ) if img_corners[0].max() <= 1224 else 1224 ymin = img_corners[1].min() if img_corners[1].min() >= 0 else 0 ymax = img_corners[1].max( ) if img_corners[1].max() <= 1024 else 1024 if xmax - xmin <= 0 or ymax - ymin <= 0: continue bounds = Bounds2D(xmin, ymin, xmax - xmin, ymax - ymin) # car, pedestrian, animal, other_vehicle, bus, motorcycle, truck, emergency_vehicle, bicycle label = box.name if label is not None: class_index = classes.index(box.name) # noqa annotations[str(data_path)].append( Object2D(bounds, class_index)) # noqa return Dataset(DATASET_NAME, images, classes, annotations)
def _mocked(path: str) -> Dataset: images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} for i, class_name in enumerate(os.listdir(path)): classes.append(class_name) class_folder = os.path.join(path, class_name) for file in os.listdir(class_folder): image_path = os.path.join(class_folder, file) images.append(image_path) annotations[image_path] = [Object2D(Bounds2D(0, 0, 0, 0), i)] return Dataset(DATASET_NAME, images, classes, annotations)
def _lisa_signs(path: str) -> Dataset: # pylint: disable=too-many-locals images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} annotations_path = os.path.join(path, "allAnnotations.csv") if not os.path.exists(annotations_path): raise FileNotFoundError("Could not find annotations file {annotations_path} in LISA Signs dataset.") # Read annotations with open(annotations_path, "r") as annotations_file: reader = csv.reader(annotations_file, delimiter=";") for i, row in enumerate(reader): # Skip the first row, it is just headers if i == 0: continue image_name = row[0] image_path = os.path.join(path, image_name) detection_class = row[1] # Calculate the position and dimensions of the bounding box x_min = int(row[2]) # x-coordinate of top left corner y_min = int(row[3]) # y-coordinate of top left corner x_max = int(row[4]) # x-coordinate of bottom right corner y_max = int(row[5]) # y-coordinate of bottom right corner # Get the class index if it has already been registered # otherwise register it and select the index try: class_index = classes.index(detection_class) except ValueError: class_index = len(classes) classes.append(detection_class) # Package the detection images.append(image_path) if image_path not in annotations: annotations[image_path] = [] annotations[image_path].append(Object2D(Bounds2D(x_min, y_min, x_max - x_min, y_max - y_min), class_index)) return Dataset(SIGN_DATASET_NAME, images, classes, annotations)
def _bosch(path: str) -> Dataset: # pylint:disable=too-many-locals images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} annotations_path = os.path.join(path, "train.yaml") if not os.path.isfile(annotations_path): raise FileNotFoundError( f"Could not find annotations file {annotations_path}.") with open(annotations_path, "r") as file: raw_annotations = yaml.load(file) for annotation in raw_annotations: detections = annotation["boxes"] image_path = os.path.abspath(os.path.join(path, annotation["path"])) for detection in detections: label = detection["label"] x_min = round(detection["x_min"]) x_max = round(detection["x_max"]) y_min = round(detection["y_min"]) y_max = round(detection["y_max"]) # Get the class index if it has already been registered otherwise register it and select the index try: class_index = classes.index(label) except ValueError: class_index = len(classes) classes.append(label) # Package the detection if image_path not in annotations: annotations[image_path] = [] images.append(image_path) annotations[image_path].append( Object2D(Bounds2D(x_min, y_min, x_max - x_min, y_max - y_min), class_index)) return Dataset(DATASET_NAME, images, classes, annotations)
def _scale_od_ped(path: str) -> Dataset: # noqa images: Dataset.Images = [] classes: Dataset.Classes = ["Pedestrian"] annotations: Dataset.Annotations = {} images_path = os.path.join(path, "training", "image_2") labels_path = os.path.join(path, "training", "label_pedonly") for image_name in os.listdir(images_path): image_path = os.path.join(images_path, image_name) base_name = image_name.split(".")[0] label_path = os.path.join(labels_path, base_name + ".txt") if os.path.exists(label_path): images.append(image_path) image_annotations = [] with open(label_path, "r") as file: for line in file: bounds = Bounds2D(*[float(s) for s in line.split()[4:8]]) image_annotations.append(Object2D(bounds, 0)) annotations[image_path] = image_annotations return Dataset(DATASET_NAME, images, classes, annotations)
def _nuscenes(path: str) -> Dataset: # noqa images: Dataset.Images = [] classes: Dataset.Classes = DETECTION_NAMES annotations: Dataset.Annotations = {} nusc = NuScenes(version="v1.0-trainval", dataroot=path) for sample in nusc.sample: for cam in CAMERAS: cam_token = sample['data'][cam] #Returns the data path as well as all annotations related to that sample_data. #Note that the boxes are transformed into the current sensor's coordinate frame. data_path, boxes, camera_intrinsic = nusc.get_sample_data( cam_token, box_vis_level=BoxVisibility.ALL) images.append(data_path) annotations[data_path] = [] for box in boxes: img_corners = view_points(box.corners(), camera_intrinsic, normalize=True)[:2, :] # Take an outer rect of the 3d projection xmin = img_corners[0].min() xmax = img_corners[0].max() ymin = img_corners[1].min() ymax = img_corners[1].max() bounds = Bounds2D(xmin, ymin, xmax - xmin, ymax - ymin) label = category_to_detection_name(box.name) if label is not None: class_index = classes.index( category_to_detection_name(box.name)) annotations[data_path].append(Object2D( bounds, class_index)) return Dataset(DATASET_NAME, images, classes, annotations)
def benchmark(model: Model, dataset: Dataset, *, proportion: float = 0.1, overlap_threshold: float = 0.5) -> Tuple[float, ConfusionMatrix]: # Get the classes and annotations and generate the confusion matrix with the `none` class classes = dataset.classes + ["__none__"] annotations = dataset.annotations confusion_matrix: ConfusionMatrix = { class_name: { class_name: 0 for class_name in classes } for class_name in classes } total_iou = 0.0 count = 0 proportion_test = [0.1,0.9] print('-------',type(dataset.split(proportion_test)[0].images)) # Flatten the images from the different datasets and iterate through each image_paths = [ image_path for image_path in dataset.split(proportion_test)[0].images #for image_path in image_paths ] # image_paths = [ # image_path for image_paths in dataset.image_split(proportion)[0].values() # for image_path in image_paths # ] total_processed = 0 for image_path in tqdm(image_paths): print(type(annotations[image_path][0].bounds)) total_processed += 1 # Grab the ground truths for this image and package them under a `PredictedObject2D` # to make statistics easier to work with ground_truths = [label for label in annotations[image_path]] '''ground_truths = [PredictedObject2D( Bounds2D( label["x_min"], label["y_min"], label["x_max"] - label["x_min"], label["y_max"] - label["y_min"] ), [classes[label["class"]]] ) for label in annotations[image_path]]''' # Keep track of which ground truths were found to get false negatives detected = [False] * len(ground_truths) # Predict on this image and iterate through each prediction to check for matches print(image_path) image = cv2.imread(image_path) #cv2.imshow('image',image) print('-------------',image.shape) print(image) predictions = model.predict(image) # image = put_labels_on_image(image, annotations[image_path]) for prediction in predictions: if 0.15*image.shape[1] > prediction.bounding_box.left or 0.85*image.shape[1] < (prediction.bounding_box.left + prediction.bounding_box.width): continue any_detected = False # Look through for i, ground_truth in enumerate(ground_truths): iou = prediction.bounding_box.iou(ground_truth.bounding_box) overlapping = iou >= overlap_threshold same_class = prediction.predicted_classes[0] == ground_truth.predicted_classes[0] if overlapping: any_detected = True if not detected[i]: confusion_matrix[ground_truth.predicted_classes[0]][prediction.predicted_classes[0]] += 1 detected[i] = True if same_class: total_iou += iou count += 1 # image = put_predictions_on_image(image, [prediction]) if not any_detected: confusion_matrix["__none__"][prediction.predicted_classes[0]] += 1 for i, is_detected in enumerate(detected): if not is_detected: confusion_matrix[ground_truths[i].predicted_classes[0]]["__none__"] += 1 # cv2.imshow("visualization", image) # key = cv2.waitKey(0) # while key != 27: # key = cv2.waitKey(0) return total_iou / count, confusion_matrix
def getDataset(self, path: str) -> Dataset: # use the same dataset for both but look for word train or test in either. is_train = True # default is train. is_full = False if "test" in path: path = path[:len(path) - len("_test")] is_train = False elif "_train" in path: if "sam" in path: path = path[:len(path) - len("_train_sam")] elif "manav" in path: path = path[:len(path) - len("_train_manav")] elif "helen" in path: path = path[:len(path) - len("_train_helen")] elif "matthieu" in path: path = path[:len(path) - len("_train_matthieu")] else: path = path[:len(path) - len("_train")] else: is_full = True if is_train: print("Path: " + path + " for training") else: print("Path: " + path + " for testing") if not os.path.isdir(path): raise FileNotFoundError( "Could not find Y4Signs dataset on path: " + path) images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} # list of classes [str] in set01/obj.names try: classes = open(os.path.join(path, "set01", "obj.names")).read().splitlines() except FileNotFoundError: print("Could not find obj.names in set01") list_of_sets = os.listdir(path) total_annotations = 0 class_limit = Counter() class_stats = Counter() for set_ in list_of_sets: f = open(os.path.join(path, set_, "train.txt")) #list of all absolute paths from train.txt. extra /data out for rel_image_path in f.read().split(): # absolute image path to the image. abs_image_path = os.path.join(path, set_, rel_image_path[5:]) # annotations file for corresponding image annotation_file_path = abs_image_path[:-4] + ".txt" try: annotation_file = open(annotation_file_path) except FileNotFoundError: print("annotation file " + annotation_file_path + " missing...skipping") continue # continue inner loop temp_annotations = [] classnums = Counter() flag = True # read the annotations file and loop through each line. for bounding_box in annotation_file.read().splitlines(): # split each line with spaces to get the [class, x1, y1, x2, y2] annotation_arr = bounding_box.strip().split(" ") # check if legal annotation if not len(annotation_arr) == 5: raise InvalidBoundingBoxError(annotation_file_path) label_class = int(annotation_arr[0]) xcent = int(float(annotation_arr[1]) * self.img_width) ycent = int(float(annotation_arr[2]) * self.img_height) width = int(float(annotation_arr[3]) * self.img_width) height = int(float(annotation_arr[4]) * self.img_height) xmin = int(xcent - 0.5 * width) ymin = int(ycent - 0.5 * height) # Construct and append an Object2D object temp_annotations.append( Object2D(Bounds2D( xmin, ymin, width, height, ), label_class)) class_limit[label_class] += 1 classnums[label_class] += 1 flag = flag and (class_limit[label_class] >= self.per_class_limit) # flag = False signifies that the image along with annotations should go to the testbatch. if (flag and is_train) or (not flag and not is_train) or is_full: for key in classnums: class_stats[key] += classnums[key] total_annotations += len(temp_annotations) images.append(abs_image_path) # add(abs_image_path, temp_annotation: list) key value pair. annotations[abs_image_path] = temp_annotations print("Annotation stats: ") for key in class_stats: print(str(classes[key]) + ": " + str(class_stats[key])) if is_train: print("Dataset type: training") else: print("Dataset type: test") print("Found " + str(len(classes)) + " classes") print("Found " + str(len(images)) + " images") print("\nTotal annotations: " + str(total_annotations)) return Dataset(self.dataset_name, images, classes, annotations)
def _scale_common(name: str, path: str, project: str, batch: Union[str, List[str]] = None) -> Dataset: # noqa images: Dataset.Images = [] classes: Dataset.Classes = [] annotations: Dataset.Annotations = {} scale_data_path = os.path.join(path, 'images') available_batches = requests.get( "https://api.scale.com/v1/batches?project={}".format(project), headers=HEADERS, auth=(SCALE_API_KEY, '')).json() batch_names = [ b['name'] for b in available_batches['docs'] if b['status'] == 'completed' ] if (batch or batch == '') and isinstance( batch, str) and batch not in batch_names + ['']: raise ValueError("Batch name {} does not exist".format(batch)) if batch and isinstance(batch, list): for bat in batch: if bat not in batch_names: raise ValueError("Batch name {} does not exist".format(bat)) client = scaleapi.ScaleClient(SCALE_API_KEY) if batch is None: batches_to_retrieve = batch_names elif isinstance(batch, str) or batch == '': batches_to_retrieve = [batch] else: batches_to_retrieve = batch print(batches_to_retrieve) regex = "([\w-]){33}|([\w-]){19}" # noqa for batch_name in batches_to_retrieve: print('On Batch', batch_name) proper_batch_name = batch_name if batch_name else 'default' batch_path = os.path.join(scale_data_path, proper_batch_name) count = 0 offset = 0 has_next_page = True needs_download = False if not os.path.exists(scale_data_path): os.makedirs(scale_data_path) if not os.path.exists(batch_path): os.makedirs(batch_path) needs_download = True while has_next_page: tasklist = client.tasks(status="completed", project=project, batch=batch_name, offset=offset) offset += 100 for obj in tasklist: task_id = obj.param_dict['task_id'] task = client.fetch_task(task_id) bbox_list = task.param_dict['response']['annotations'] img_url = task.param_dict['params']['attachment'] try: if 'drive.google.com' in img_url: match = re.search(regex, img_url) task_id = match[0] # noqa api_initialize() file_name = print_file_metadata(SERVICE, task_id) # noqa local_path = os.path.join(batch_path, file_name) # request_=urllib.request.Request(img_url,None,headers) # remotefile = urllib.request.urlopen(request_) # #remotefile = urllib.request.urlopen(img_url) # content = remotefile.info()['Content-Disposition'] # _, params = cgi.parse_header(content) # local_path = os.path.join(batch_path, params["filename"]) else: local_path = os.path.join(batch_path, img_url.rsplit('/', 1)[-1]) if needs_download or not os.path.isfile(local_path): print('Batch Path', batch_path) print('Local Path', local_path) # Download the image # urllib.request.urlretrieve(img_url, local_path) request_ = urllib.request.Request( img_url, None, headers) response = urllib.request.urlopen(request_) local_file = open(local_path, 'wb') local_file.write(response.read()) local_file.close() except HTTPError as error: print( "Image {} failed to download due to HTTPError {}: {}". format(img_url, error.code, error.reason)) continue except TypeError as error: print( "Image {} failed to download due to improper header: {}" .format(img_url, str(error))) continue annotations[local_path] = [] for bbox in bbox_list: # Get the label of the detected object detection_class = bbox['label'] # Calculate the position and dimensions of the bounding box x_min = int( bbox['left']) # x-coordinate of top left corner y_min = int(bbox['top']) # y-coordinate of top left corner width = int(bbox['width']) # width of the bounding box height = int(bbox['height']) # height of the bounding box # Get the class index if it has already been registered # otherwise register it and select the index try: class_index = classes.index(detection_class) except ValueError: class_index = len(classes) classes.append(detection_class) # Package the detection annotations[local_path].append( Object2D(Bounds2D(x_min, y_min, width, height), class_index)) images.append(local_path) print("Processed {}\r".format(local_path), end="") count += 1 if len(tasklist) < 100 or count > MAX_TO_PROCESS: has_next_page = False return Dataset(name, images, classes, annotations)