Source code for kitcar_ml.utils.evaluation.test.basic_utility

import itertools
import math

import more_itertools
import numpy as np

from kitcar_ml.utils.bounding_box import BoundingBox


[docs]def lcm(a, b): """Calculate the least common multiple of two numbers.""" return abs(a * b) // math.gcd(a, b)
[docs]def create_bounding_boxes( accuracy=0.5, num_images=10, num_classes=1, max_boxes=1000, confidence=0.5 ): """Create bounding boxes for detections and the groundtruth. Args: accuracy: The accuracy of the detections. num_images: The number of images. num_classes: The number of classes. max_boxes: The maximal number of bounding boxes. confidence: The confidence of inaccurate bounding boxes. Returns: The list of groundtruth and detection bounding boxes per image and the resulting accuracy of the bounding boxes, because it can happen that crocked accurcay get rounded a bit. """ if accuracy == 0: num_boxes = num_images * 10 else: num_boxes = lcm(lcm(math.ceil(1 / accuracy), num_classes), num_images) * num_images num_boxes = min(max_boxes, num_boxes) return create_bounding_boxes_by_amount( accuracy=accuracy, num_images=num_images, num_classes=num_classes, confidence=confidence, )
[docs]def create_bounding_boxes_by_amount( accuracy=0.5, num_images=10, num_classes=1, num_boxes=100, confidence=0.5, ): """Create bounding boxes for detections and the groundtruth. Args: accuracy: The accuracy of the detections. num_images: The number of images. num_classes: The number of classes. num_boxes: The number of bounding boxes. confidence: The confidence of inaccurate bounding boxes. Returns: The list of groundtruth and detection bounding boxes per image and the resulting accuracy of the bounding boxes, because it can happen that crocked accurcay get rounded a bit. """ # Assure should be divisible by the images positives = num_boxes * accuracy classes_iter = itertools.cycle(str(x) for x in range(num_classes)) accuracy_indices = [i < positives for i in range(num_boxes)] permuted_accuracy_indices = [ np.random.permutation(indices) for indices in more_itertools.chunked(accuracy_indices, num_boxes // num_images) ] random_points = np.random.rand(num_boxes, 2) * 10 # Split random_points for all images point1 = np.split(random_points, num_images) # Endpoint of the box is just 10 pixel further. point2 = np.add(point1, 10) # Concatenate box endpoints to get the whole box. bbs = np.concatenate((point1, point2), axis=2) gts = [ [BoundingBox(*bb, cls) for bb, cls in zip(image_bbs, classes_iter)] for image_bbs in bbs ] dets = [ [ BoundingBox(*gt.coordinates, gt.class_label, 1) if indices[i] else BoundingBox(25, 25, 30, 30, gt.class_label, confidence=confidence) for i, gt in enumerate(img_gts) ] for img_gts, indices in zip(gts, permuted_accuracy_indices) ] accuracy = int(math.ceil(positives)) / num_boxes return gts, dets, accuracy