cats = ['Standing', 'Fallen']
outpath = Path('example_data/tiles/')
yolo_proc = YOLOProcessor(outpath, outpath, cats)
yolo_proc.from_shp('label', ann_format='box')yolo utilities
Conversion between geospatial data and yolo-format
Specifications of yolo format:
- The folder structure must be so that images are in a folder called
imagesand annotations in a folderlabels - Each image must have a corresponding annotation file with a same name aside from file type (
txt) - Each
txtcontains all annotations in separate rows- Bounding box annotation format is
classidx_centery_centerwidthheight - Polygon annotation format
classidxyxy…
- Bounding box annotation format is
- Coordinates are normalized between 0 and 1, so that origin is at upper left and (1,1) in bottom right
- Train/val/test -sets are collated in separate files, with the paths to image files
- Information is collated on a
yamlfile, wherepath: <path>is the dataset root dirtrain:,val:andtest:are either:- directories
- txt-files containing images
- list containing paths
- class names are saved like
names: 0: person 1: bicycle
YOLOProcessor
YOLOProcessor (data_path:str, outpath:str, names:list)
Handles transformations from GIS-polygons to YOLOv8-format and backwards
YOLOProcessor converts data from either shp or geojson to YOLOv5 format.
First bounding boxes.
def plot_bounding_box(image, annotation_list, classes):
annotations = np.array(annotation_list)
w, h = image.size
plotted_image = ImageDraw.Draw(image)
transformed_annotations = np.copy(annotations)
transformed_annotations[:,[1,3]] = annotations[:,[1,3]] * w
transformed_annotations[:,[2,4]] = annotations[:,[2,4]] * h
transformed_annotations[:,1] = transformed_annotations[:,1] - (transformed_annotations[:,3] / 2)
transformed_annotations[:,2] = transformed_annotations[:,2] - (transformed_annotations[:,4] / 2)
transformed_annotations[:,3] = transformed_annotations[:,1] + transformed_annotations[:,3]
transformed_annotations[:,4] = transformed_annotations[:,2] + transformed_annotations[:,4]
for ann in transformed_annotations:
obj_cls, x0, y0, x1, y1 = ann
plotted_image.rectangle(((x0,y0), (x1,y1)))
plotted_image.text((x0, y0 - 10), classes[int(obj_cls)])
plt.imshow(np.array(image))
plt.show()
# Get any random annotation file
annotation_file = random.choice(os.listdir(outpath/'labels'))
with open(outpath/'labels'/annotation_file, "r") as file:
annotation_list = file.read().split("\n")[:-1]
annotation_list = [x.split(" ") for x in annotation_list]
annotation_list = [[float(y) for y in x ] for x in annotation_list]
#Get the corresponding image file
image_file = annotation_file.replace("txt", "tif")
assert os.path.exists(outpath/'images'/image_file)
#Load the image
image = Image.open(outpath/'images'/image_file)
#Plot the Bounding Box
plot_bounding_box(image, annotation_list, {0:'Standing', 1:'Fallen'})
Then to polygon.
cats = ['Standing', 'Fallen']
outpath = Path('example_data/tiles/')
yolo_proc = YOLOProcessor(outpath, outpath, cats)
yolo_proc.from_shp('label', ann_format='polygon')def plot_polygon(image, annotation_list, classes):
w, h = image.size
plotted_image = ImageDraw.Draw(image)
for ann in annotation_list:
obj_cls = ann[0]
xcoords = [ann[i]*w for i in range(1, len(ann), 2)]
ycoords = [ann[i]*h for i in range(2, len(ann)+1, 2)]
xcoords.append(xcoords[0])
ycoords.append(ycoords[0])
plotted_image.polygon(list(zip(xcoords, ycoords)))
plotted_image.text((xcoords[0], ycoords[0] - 10), classes[int(obj_cls)])
plt.imshow(np.array(image))
plt.show()# Get any random annotation file
annotation_file = random.choice(os.listdir(outpath/'labels'))
with open(outpath/'labels'/annotation_file, "r") as file:
annotation_list = file.read().split("\n")[:-1]
annotation_list = [x.split(" ") for x in annotation_list]
annotation_list = [[float(y) for y in x ] for x in annotation_list]
#Get the corresponding image file
image_file = annotation_file.replace("txt", "tif")
assert os.path.exists(outpath/'images'/image_file)
#Load the image
image = Image.open(outpath/'images'/image_file)
#Plot the Bounding Box
plot_polygon(image, annotation_list, {0:'Standing', 1:'Fallen'})
Rotated bounding boxes are saved as polygon-style annotations.
cats = ['Standing', 'Fallen']
outpath = Path('example_data/tiles/')
yolo_proc = YOLOProcessor(outpath, outpath, cats)
yolo_proc.from_shp('label', ann_format='rotated box')# Get any random annotation file
annotation_file = random.choice(os.listdir(outpath/'labels'))
with open(outpath/'labels'/annotation_file, "r") as file:
annotation_list = file.read().split("\n")[:-1]
annotation_list = [x.split(" ") for x in annotation_list]
annotation_list = [[float(y) for y in x ] for x in annotation_list]
#Get the corresponding image file
image_file = annotation_file.replace("txt", "tif")
assert os.path.exists(outpath/'images'/image_file)
#Load the image
image = Image.open(outpath/'images'/image_file)
#Plot the Bounding Box
plot_polygon(image, annotation_list, {0:'Standing', 1:'Fallen'})