Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/C4 - Convolutional Neural Networks/Week 3/Car detection for Autonomous Driving/yad2k/utils/utils.py
Views: 4822
"""Draw predicted or ground truth boxes on input image."""1import imghdr2import colorsys3import random45import numpy as np6from PIL import Image, ImageDraw, ImageFont7from tensorflow.keras import backend as K89from functools import reduce1011def preprocess_image(img_path, model_image_size):12image_type = imghdr.what(img_path)13image = Image.open(img_path)14resized_image = image.resize(tuple(reversed(model_image_size)), Image.BICUBIC)15image_data = np.array(resized_image, dtype='float32')16image_data /= 255.17image_data = np.expand_dims(image_data, 0) # Add batch dimension.18return image, image_data1920def compose(*funcs):21"""Compose arbitrarily many functions, evaluated left to right.2223Reference: https://mathieularose.com/function-composition-in-python/24"""25# return lambda x: reduce(lambda v, f: f(v), funcs, x)26if funcs:27return reduce(lambda f, g: lambda *a, **kw: g(f(*a, **kw)), funcs)28else:29raise ValueError('Composition of empty sequence not supported.')3031def read_classes(classes_path):32with open(classes_path) as f:33class_names = f.readlines()34class_names = [c.strip() for c in class_names]35return class_names3637def read_anchors(anchors_path):38with open(anchors_path) as f:39anchors = f.readline()40anchors = [float(x) for x in anchors.split(',')]41anchors = np.array(anchors).reshape(-1, 2)42return anchors4344def scale_boxes(boxes, image_shape):45""" Scales the predicted boxes in order to be drawable on the image"""46height = image_shape[0] * 1.047width = image_shape[1] * 1.048image_dims = K.stack([height, width, height, width])49image_dims = K.reshape(image_dims, [1, 4])50boxes = boxes * image_dims51return boxes5253def get_colors_for_classes(num_classes):54"""Return list of random colors for number of classes given."""55# Use previously generated colors if num_classes is the same.56if (hasattr(get_colors_for_classes, "colors") and57len(get_colors_for_classes.colors) == num_classes):58return get_colors_for_classes.colors5960hsv_tuples = [(x / num_classes, 1., 1.) for x in range(num_classes)]61colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))62colors = list(63map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),64colors))65random.seed(10101) # Fixed seed for consistent colors across runs.66random.shuffle(colors) # Shuffle colors to decorrelate adjacent classes.67random.seed(None) # Reset seed to default.68get_colors_for_classes.colors = colors # Save colors for future calls.69return colors7071def textsize(text, font):72im = Image.new(mode="P", size=(0, 0))73draw = ImageDraw.Draw(im)74_, _, width, height = draw.textbbox((0, 0), text=text, font=font)75return width, height7677def draw_boxes(image, boxes, box_classes, class_names, scores=None):78"""Draw bounding boxes on image.7980Draw bounding boxes with class name and optional box score on image.8182Args:83image: An `array` of shape (width, height, 3) with values in [0, 1].84boxes: An `array` of shape (num_boxes, 4) containing box corners as85(y_min, x_min, y_max, x_max).86box_classes: A `list` of indicies into `class_names`.87class_names: A `list` of `string` class names.88`scores`: A `list` of scores for each box.8990Returns:91A copy of `image` modified with given bounding boxes.92"""93#image = Image.fromarray(np.floor(image * 255 + 0.5).astype('uint8'))9495font = ImageFont.truetype(96font='font/FiraMono-Medium.otf',97size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))98thickness = (image.size[0] + image.size[1]) // 30099100colors = get_colors_for_classes(len(class_names))101102for i, c in list(enumerate(box_classes)):103box_class = class_names[c]104box = boxes[i]105106if isinstance(scores.numpy(), np.ndarray):107score = scores.numpy()[i]108label = '{} {:.2f}'.format(box_class, score)109else:110label = '{}'.format(box_class)111112draw = ImageDraw.Draw(image)113label_size = textsize(label, font)114115top, left, bottom, right = box116top = max(0, np.floor(top + 0.5).astype('int32'))117left = max(0, np.floor(left + 0.5).astype('int32'))118bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))119right = min(image.size[0], np.floor(right + 0.5).astype('int32'))120print(label, (left, top), (right, bottom))121122if top - label_size[1] >= 0:123text_origin = np.array([left, top - label_size[1]])124else:125text_origin = np.array([left, top + 1])126127# My kingdom for a good redistributable image drawing library.128for i in range(thickness):129draw.rectangle(130[left + i, top + i, right - i, bottom - i], outline=colors[c])131draw.rectangle(132[tuple(text_origin), tuple(text_origin + label_size)],133fill=colors[c])134draw.text(text_origin, label, fill=(0, 0, 0), font=font)135del draw136137return np.array(image)138139140