shell-size-app / spatstatapp /plotting.py
HarryEslick's picture
src removed
b91a8b9
from typing import List
from spatstatapp.paths import find_label_path
from spatstatapp.tile_training_data import load_bboxes
import cv2
import numpy as np
import supervision as sv
from ultralytics.utils.ops import xywhn2xyxy
def coco_to_detections(label_path, image, id_to_label = {0:"scallop"}):
bboxes = load_bboxes(label_path)
class_id = np.array(bboxes)[:,0].astype(int)
class_name = np.vectorize(id_to_label.get)(class_id)
bboxes = np.array(bboxes)[:,1:] # remove class_id
xyxy = xywhn2xyxy(bboxes,
w = image.shape[1],
h = image.shape[0])
xyxy = np.clip(xyxy, a_min=0, a_max=max(image.shape))
detections = sv.Detections(
xyxy=xyxy,
# class_id=np.array(len(xyxy)*[0]),
class_id=class_id,
data = {"class_name":class_name}
)
return detections
def draw_img_bboxes(img_path):
image = cv2.imread(img_path)
label_path = find_label_path(img_path)
detections = coco_to_detections(label_path, image)
box_annotator = sv.BoxAnnotator()
annotated_frame = box_annotator.annotate(
scene=image.copy(),
detections=detections
)
return annotated_frame
def stack_images_grid(images):
num_images = len(images)
grid_size = int(np.ceil(np.sqrt(num_images)))
# Calculate the size of the grid
img_height, img_width, _ = images[0].shape
buffer = 2
grid_height = grid_size * img_height + (grid_size - 1) * buffer
grid_width = grid_size * img_width + (grid_size - 1) * buffer
# Create a white canvas
grid_image = np.ones((grid_height, grid_width, 3), dtype=np.uint8) * 255
for idx, img in enumerate(images):
row = idx // grid_size
col = idx % grid_size
y = row * (img_height + buffer)
x = col * (img_width + buffer)
grid_image[y:y+img_height, x:x+img_width, :] = img
return grid_image
def show_img_bboxes(img_path):
annotated_frame = draw_img_bboxes(img_path)
sv.plot_image(annotated_frame)
def annotate_DetectionDataset(dataset: sv.DetectionDataset, idxs:List[int]|int):
if isinstance(idxs, int):
idxs = np.random.choice(len(dataset), size=idxs, replace=False).tolist()
frames = []
for i in idxs:
path, img, detections = dataset[i]
box_annotator = sv.BoxAnnotator()
frames.append(box_annotator.annotate(
scene=img.copy(),
detections=detections
))
return frames
def show_img_bboxes_grid(img_paths):
"""
shows a grid of images with bounding boxes from list of paths
Args:
img_paths: list of image paths
Example:
show_img_bboxes_grid((data_dir/"images/train").glob("*.jpg")[0:16])
"""
images = [draw_img_bboxes(img_path) for img_path in img_paths]
annotated_grid = stack_images_grid(images)
sv.plot_image(annotated_grid)
def show_dataset_bboxes_grid(dataset: sv.DetectionDataset, idxs:List[int]|int):
"""
shows a grid of images with bounding boxes from the dataset
Args:
dataset: sv.DetectionDataset: _description_
idxs: list of indices to show or int: number of random indices to show
Example:
data_dir = Path('dataset_clipped')
dd = sv.DetectionDataset.from_yolo(
images_directory_path= data_dir/"images/train",
annotations_directory_path= data_dir/"labels/train",
data_yaml_path="data.yaml",
)
show_dataset_bboxes_grid(dd, 16)
"""
images = annotate_DetectionDataset(dataset, idxs)
annotated_grid = stack_images_grid(images)
sv.plot_image(annotated_grid)