= ['Standing', 'Fallen']
cats
= Path('example_data/tiles/')
outpath = YOLOProcessor(outpath, outpath, cats)
yolo_proc 'label', ann_format='box') yolo_proc.from_shp(
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
images
and annotations in a folderlabels
- Each image must have a corresponding annotation file with a same name aside from file type (
txt
) - Each
txt
contains all annotations in separate rows- Bounding box annotation format is
classid
x_center
y_center
width
height
- Polygon annotation format
classid
x
y
x
y
…
- 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
yaml
file, 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):
= np.array(annotation_list)
annotations = image.size
w, h = ImageDraw.Draw(image)
plotted_image
= 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]
transformed_annotations[:,
for ann in transformed_annotations:
= ann
obj_cls, x0, y0, x1, y1
plotted_image.rectangle(((x0,y0), (x1,y1)))
- 10), classes[int(obj_cls)])
plotted_image.text((x0, y0
plt.imshow(np.array(image))
plt.show()
# Get any random annotation file
= random.choice(os.listdir(outpath/'labels'))
annotation_file with open(outpath/'labels'/annotation_file, "r") as file:
= 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]
annotation_list
#Get the corresponding image file
= annotation_file.replace("txt", "tif")
image_file assert os.path.exists(outpath/'images'/image_file)
#Load the image
= Image.open(outpath/'images'/image_file)
image
#Plot the Bounding Box
0:'Standing', 1:'Fallen'}) plot_bounding_box(image, annotation_list, {
Then to polygon.
= ['Standing', 'Fallen']
cats
= Path('example_data/tiles/')
outpath = YOLOProcessor(outpath, outpath, cats)
yolo_proc 'label', ann_format='polygon') yolo_proc.from_shp(
def plot_polygon(image, annotation_list, classes):
= image.size
w, h = ImageDraw.Draw(image)
plotted_image
for ann in annotation_list:
= ann[0]
obj_cls = [ann[i]*w for i in range(1, len(ann), 2)]
xcoords = [ann[i]*h for i in range(2, len(ann)+1, 2)]
ycoords 0])
xcoords.append(xcoords[0])
ycoords.append(ycoords[list(zip(xcoords, ycoords)))
plotted_image.polygon(
0], ycoords[0] - 10), classes[int(obj_cls)])
plotted_image.text((xcoords[
plt.imshow(np.array(image)) plt.show()
# Get any random annotation file
= random.choice(os.listdir(outpath/'labels'))
annotation_file with open(outpath/'labels'/annotation_file, "r") as file:
= 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]
annotation_list
#Get the corresponding image file
= annotation_file.replace("txt", "tif")
image_file assert os.path.exists(outpath/'images'/image_file)
#Load the image
= Image.open(outpath/'images'/image_file)
image
#Plot the Bounding Box
0:'Standing', 1:'Fallen'}) plot_polygon(image, annotation_list, {
Rotated bounding boxes are saved as polygon-style annotations.
= ['Standing', 'Fallen']
cats
= Path('example_data/tiles/')
outpath = YOLOProcessor(outpath, outpath, cats)
yolo_proc 'label', ann_format='rotated box') yolo_proc.from_shp(
# Get any random annotation file
= random.choice(os.listdir(outpath/'labels'))
annotation_file with open(outpath/'labels'/annotation_file, "r") as file:
= 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]
annotation_list
#Get the corresponding image file
= annotation_file.replace("txt", "tif")
image_file assert os.path.exists(outpath/'images'/image_file)
#Load the image
= Image.open(outpath/'images'/image_file)
image
#Plot the Bounding Box
0:'Standing', 1:'Fallen'}) plot_polygon(image, annotation_list, {