yoloWRKSHP box formats#
Notebook by:
Royi Avital RoyiAvital@fixelalgorithms.com
Revision History#
Version |
Date |
User |
Content / Changes |
|---|---|---|---|
1.0.000 |
16/06/2024 |
Royi Avital |
First version |
# Import Packages
# General Tools
import numpy as np
import scipy as sp
import pandas as pd
# Machine Learning
# Deep Learning
# Miscellaneous
from enum import auto, Enum, unique
import math
import os
from platform import python_version
import random
import time
# Typing
from typing import Callable, Dict, Generator, List, Optional, Self, Set, Tuple, Union
# Visualization
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
# Jupyter
from IPython import get_ipython
from IPython.display import HTML, Image
from IPython.display import display
from ipywidgets import Dropdown, FloatSlider, interact, IntSlider, Layout, SelectionSlider
from ipywidgets import interact
Notations#
(?) Question to answer interactively.
(!) Simple task to add code for the notebook.
(@) Optional / Extra self practice.
(#) Note / Useful resource / Food for thought.
Code Notations:
someVar = 2; #<! Notation for a variable
vVector = np.random.rand(4) #<! Notation for 1D array
mMatrix = np.random.rand(4, 3) #<! Notation for 2D array
tTensor = np.random.rand(4, 3, 2, 3) #<! Notation for nD array (Tensor)
tuTuple = (1, 2, 3) #<! Notation for a tuple
lList = [1, 2, 3] #<! Notation for a list
dDict = {1: 3, 2: 2, 3: 1} #<! Notation for a dictionary
oObj = MyClass() #<! Notation for an object
dfData = pd.DataFrame() #<! Notation for a data frame
dsData = pd.Series() #<! Notation for a series
hObj = plt.Axes() #<! Notation for an object / handler / function handler
Code Exercise#
Single line fill
vallToFill = ???
Multi Line to Fill (At least one)
# You need to start writing
????
Section to Fill
#===========================Fill This===========================#
# 1. Explanation about what to do.
# !! Remarks to follow / take under consideration.
mX = ???
???
#===============================================================#
# Configuration
# %matplotlib inline
seedNum = 512
np.random.seed(seedNum)
random.seed(seedNum)
# Matplotlib default color palette
lMatPltLibclr = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
# sns.set_theme() #>! Apply SeaBorn theme
runInGoogleColab = 'google.colab' in str(get_ipython())
# Constants
FIG_SIZE_DEF = (8, 8)
ELM_SIZE_DEF = 50
CLASS_COLOR = ('b', 'r')
EDGE_COLOR = 'k'
MARKER_SIZE_DEF = 10
LINE_WIDTH_DEF = 2
# Download Auxiliary Modules for Google Colab
# Courses Packages
# General Auxiliary Functions
@unique
class BBoxFormat(Enum):
# Bounding Box Format, See https://albumentations.ai/docs/getting_started/bounding_boxes_augmentation
COCO = auto()
PASCAL_VOC = auto()
YOLO = auto()
Box Standards Conversion#
There are 3
COCO Style:
[x, y, width, height].PASCAL VOC Style:
[x_min, y_min, x_max, y_max].YOLO Style:
[x_center, y_center, width, height].
(#) The YOLO style is normalized to the image dimensions.
This notebook implements the conversion between all standards.
# Parameters
# Data
Implementation#
The data is synthetic data.
Each image includes Ellipses where its color is the class (R, G, B) and the bounding rectangle.
(#) The label, per object, is a vector of
5:[Class, xCenter, yCenter, boxWidth, boxHeight].(#) The label is in
YOLOformat, hence it is normalized to[0, 1].
# Box Standard Conversion
def ConvertBBoxFormat( vBox: np.ndarray, tuImgSize: Tuple[int, int], boxFormatIn: BBoxFormat, boxFormatOut: BBoxFormat ) -> np.ndarray:
# tuImgSize = (numRows, numCols) <=> (imgHeight, imgWidth)
imgHeight, imgWidth = tuImgSize
if boxFormatIn == boxFormatOut:
return vBox
# Convert input box to PASCAL VOC format as an intermediate format
if boxFormatIn == BBoxFormat.COCO:
x_min = vBox[0]
y_min = vBox[1]
x_max = vBox[0] + vBox[2]
y_max = vBox[1] + vBox[3]
elif boxFormatIn == BBoxFormat.YOLO:
x_center = vBox[0] * imgWidth
y_center = vBox[1] * imgHeight
width = vBox[2] * imgWidth
height = vBox[3] * imgHeight
x_min = x_center - width / 2
y_min = y_center - height / 2
x_max = x_center + width / 2
y_max = y_center + height / 2
elif boxFormatIn == BBoxFormat.PASCAL_VOC:
x_min = vBox[0]
y_min = vBox[1]
x_max = vBox[2]
y_max = vBox[3]
# Convert from PASCAL VOC format to the output format
if boxFormatOut == BBoxFormat.COCO:
vB = np.array([x_min, y_min, x_max - x_min, y_max - y_min])
elif boxFormatOut == BBoxFormat.YOLO:
x_center = (x_min + x_max) / 2 / imgWidth
y_center = (y_min + y_max) / 2 / imgHeight
width = (x_max - x_min) / imgWidth
height = (y_max - y_min) / imgHeight
vB = np.array([x_center, y_center, width, height])
elif boxFormatOut == BBoxFormat.PASCAL_VOC:
vB = np.array([x_min, y_min, x_max, y_max])
return vB
# Test
vBox_yolo = np.array([0.5, 0.5, 0.2, 0.2]) # YOLO format (normalized)
tuImgSize = (100, 100) # Image size (height, width)
boxFormatIn = BBoxFormat.YOLO
boxFormatOut = BBoxFormat.COCO
converted_box = ConvertBBoxFormat(vBox_yolo, tuImgSize, boxFormatIn, boxFormatOut)
print("Converted Box:", converted_box)
Converted Box: [40. 40. 20. 20.]
