Convert x y w h to top left right bottom

The CONVERT COORDINATES command converts the (x;y) coordinates of a point from one coordinate system to another. The input and output coordinate systems supported are forms (and subforms), windows, and the screen. For example, you can use this command to get the coordinates in the main form of an object belonging to a subform. This makes it easy to create a context menu at any custom position.

In and , pass as variables the (x;y) coordinates of the point you want to convert. After the command is executed, these variables will contain the converted values.

In the parameter, pass the initial coordinate system the input point is using, and in the parameter, pass the coordinate system into which it must be converted. Both parameters can take one of the following constant values, added to the "Windows" theme:

Constant Type Value Comment XY Current form Longint 1 Origin is top left corner of current form XY Current window Longint 2 Origin is top left corner of current window XY Main window Longint 4 On Windows: origin is top left corner of main window; on OS X: same as XY Screen XY Screen Longint 3 Origin is top left corner of main screen (same as for SCREEN COORDINATES command).

When this command is called from the method of a subform or a subform's object, and if one of the selectors is XY Current form, then the coordinates are relative to the subform itself, not to its parent form.

When converting from/to the position of a form window (for example when converting from the results of GET WINDOW RECT, or to values passed to Open form window), XY Main window must be used since it is the coordinate system used by window commands on Windows. It can also be used for this purpose on OS X, where it is equivalent to XY Screen.

When is XY Current form and the point is in the body section of a list form, the result depends on the calling context of the command:

  • If the command is called in the On Display Detail event, the resulting point is located in the display of the record being drawn on screen.
  • If the command is called outside of an On Display Detail event but while a record is being edited, the resulting point is located in the display of the record being edited.
  • Otherwise, the resulting point is located in the display of the first record.

Example 1

You want to open a pop-up menu at the bottom left corner of the "MyObject" object.

// OBJECT GET COORDINATES works in the current form coordinate system // Dynamic pop-up menu uses the current window coordinate system // We need to convert the values C_LONGINT($left;$top;$right;$bottom) C_TEXT($menu) OBJECT GET COORDINATES(*;"MyObject";$left;$top;$right;$bottom) CONVERT COORDINATES($left;$bottom;XY Current form;XY Current window) $menu:=Create menu APPEND MENU ITEM($menu;"Right here") APPEND MENU ITEM($menu;"Right now") Dynamic pop up menu($menu;"";$left;$bottom) RELEASE MENU($menu)

Convert x y w h to top left right bottom

Example 2

You want to open a pop-up window at the position of the mouse cursor. On Windows, you need to convert the coordinates since GET MOUSE (with the * parameter) returns values based on the position of the MDI window:

Bounding boxes are rectangles that mark objects on an image. There are multiple formats of bounding boxes annotations. Each format uses its specific representation of bouning boxes coordinates. Albumentations supports four formats:

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

4,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5, and

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

6 .

Let's take a look at each of those formats and how they represent coordinates of bounding boxes.

As an example, we will use an image from the dataset named Common Objects in Context. It contains one bounding box that marks a cat. The image width is 640 pixels, and its height is 480 pixels. The width of the bounding box is 322 pixels, and its height is 117 pixels.

The bounding box has the following

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

7 coordinates of its corners: top-left is

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

8 or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

9, top-right is

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

0 or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

1, bottom-left is

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

2 or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

3, bottom-right is

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

4 or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

5. As you see, coordinates of the bounding box's corners are calculated with respect to the top-left corner of the image which has

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

7 coordinates

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

7.

Convert x y w h to top left right bottom
An example image with a bounding box from the COCO dataset

pascal_voc

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3 is a format used by the Pascal VOC dataset. Coordinates of a bounding box are encoded with four values in pixels:

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

9.

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

0 and

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

1 are coordinates of the top-left corner of the bounding box.

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

2 and

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

3 are coordinates of bottom-right corner of the bounding box.

Coordinates of the example bounding box in this format are

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

4.

albumentations

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

4 is similar to

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3, because it also uses four values

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

9 to represent a bounding box. But unlike

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

4 uses normalized values. To normalize values, we divide coordinates in pixels for the x- and y-axis by the width and the height of the image.

Coordinates of the example bounding box in this format are

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

0 which are

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

1.

Albumentations uses this format internally to work with bounding boxes and augment them.

coco

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5 is a format used by the Common Objects in Context COCO dataset.

In

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5, a bounding box is defined by four values in pixels

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

4. They are coordinates of the top-left corner along with the width and height of the bounding box.

Coordinates of the example bounding box in this format are

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

5.

yolo

In

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

6, a bounding box is represented by four values

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

7.

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

8 and

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

9 are the normalized coordinates of the center of the bounding box. To make coordinates normalized, we take pixel values of x and y, which marks the center of the bounding box on the x- and y-axis. Then we divide the value of x by the width of the image and value of y by the height of the image.

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

0 and

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

1 represent the width and the height of the bounding box. They are normalized as well.

Coordinates of the example bounding box in this format are

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

2 which are

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

3.

Convert x y w h to top left right bottom
How different formats represent coordinates of a bounding box

Bounding boxes augmentation

Just like with images and masks augmentation, the process of augmenting bounding boxes consists of 4 steps.

  1. You import the required libraries.
  2. You define an augmentation pipeline.
  3. You read images and bounding boxes from the disk.
  4. You pass an image and bounding boxes to the augmentation pipeline and receive augmented images and boxes.

Note

Some transforms in Albumentation don't support bounding boxes. If you try to use them you will get an exception. Please refer to this article to check whether a transform can augment bounding boxes.

Step 1. Import the required libraries.

import albumentations as A import cv2

Step 2. Define an augmentation pipeline.

Here an example of a minimal declaration of an augmentation pipeline that works with bounding boxes.

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

Note that unlike image and masks augmentation,

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

4 now has an additional parameter

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

5. You need to pass an instance of

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

6 to that argument.

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

6 specifies settings for working with bounding boxes.

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

8 sets the format for bounding boxes coordinates.

It can either be

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

4,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5 or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

6. This value is required because Albumentation needs to know the coordinates' source format for bounding boxes to apply augmentations correctly.

Besides

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

8,

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

6 supports a few more settings.

Here is an example of

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

4 that shows all available settings with

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

6:

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7 and

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7 and

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8 parameters control what Albumentations should do to the augmented bounding boxes if their size has changed after augmentation. The size of bounding boxes could change if you apply spatial augmentations, for example, when you crop a part of an image or when you resize an image.

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7 is a value in pixels. If the area of a bounding box after augmentation becomes smaller than

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7, Albumentations will drop that box. So the returned list of augmented bounding boxes won't contain that bounding box.

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8 is a value between 0 and 1. If the ratio of the bounding box area after augmentation to

transformed = transform(image=image, bboxes=bboxes) transformed_image = transformed['image'] transformed_bboxes = transformed['bboxes']

4 becomes smaller than

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8, Albumentations will drop that box. So if the augmentation process cuts the most of the bounding box, that box won't be present in the returned list of the augmented bounding boxes.

Here is an example image that contains two bounding boxes. Bounding boxes coordinates are declared using the

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5 format.

Convert x y w h to top left right bottom
An example image with two bounding boxes

First, we apply the

transformed = transform(image=image, bboxes=bboxes) transformed_image = transformed['image'] transformed_bboxes = transformed['bboxes']

7 augmentation without declaring parameters

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7 and

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8. The augmented image contains two bounding boxes.

Convert x y w h to top left right bottom
An example image with two bounding boxes after applying augmentation

Next, we apply the same

transformed = transform(image=image, bboxes=bboxes) transformed_image = transformed['image'] transformed_bboxes = transformed['bboxes']

7 augmentation, but now we also use the

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7 parameter. Now, the augmented image contains only one bounding box, because the other bounding box's area after augmentation became smaller than

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

7, so Albumentations dropped that bounding box.

Convert x y w h to top left right bottom
An example image with one bounding box after applying augmentation with 'min_area'

Finally, we apply the

transformed = transform(image=image, bboxes=bboxes) transformed_image = transformed['image'] transformed_bboxes = transformed['bboxes']

7 augmentation with the

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8. After that augmentation, the resulting image doesn't contain any bounding box, because visibility of all bounding boxes after augmentation are below threshold set by

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

8.

Convert x y w h to top left right bottom
An example image with zero bounding boxes after applying augmentation with 'min_visibility'

Class labels for bounding boxes

Besides coordinates, each bounding box should have an associated class label that tells which object lies inside the bounding box. There are two ways to pass a label for a bounding box.

Let's say you have an example image with three objects:

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

6,

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

7, and

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

8. Bounding boxes coordinates in the

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5 format for those objects are

class_labels = ['cat', 'dog', 'parrot']

0,

class_labels = ['cat', 'dog', 'parrot']

1, and

class_labels = ['cat', 'dog', 'parrot']

2.

Convert x y w h to top left right bottom
An example image with 3 bounding boxes from the COCO dataset

1. You can pass labels along with bounding boxes coordinates by adding them as additional values to the list of coordinates.

For the image above, bounding boxes with class labels will become

class_labels = ['cat', 'dog', 'parrot']

3,

class_labels = ['cat', 'dog', 'parrot']

4, and

class_labels = ['cat', 'dog', 'parrot']

5.

Class labels could be of any type: integer, string, or any other Python data type. For example, integer values as class labels will look the following:

class_labels = ['cat', 'dog', 'parrot']

6,

class_labels = ['cat', 'dog', 'parrot']

7, and

class_labels = ['cat', 'dog', 'parrot']

8

Also, you can use multiple class values for each bounding box, for example

class_labels = ['cat', 'dog', 'parrot']

9,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

00, and

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

01.

2.You can pass labels for bounding boxes as a separate list (the preferred way).

For example, if you have three bounding boxes like

class_labels = ['cat', 'dog', 'parrot']

0,

class_labels = ['cat', 'dog', 'parrot']

1, and

class_labels = ['cat', 'dog', 'parrot']

2 you can create a separate list with values like

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

05, or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

06 that contains class labels for those bounding boxes. Next, you pass that list with class labels as a separate argument to the

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

07 function. Albumentations needs to know the names of all those lists with class labels to join them with augmented bounding boxes correctly. Then, if a bounding box is dropped after augmentation because it is no longer visible, Albumentations will drop the class label for that box as well. Use

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

08 parameter to set names for all arguments in

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

07 that will contain label descriptions for bounding boxes (more on that in Step 4).

Step 3. Read images and bounding boxes from the disk.

Read an image from the disk.

image = cv2.imread("/path/to/image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

Bounding boxes can be stored on the disk in different serialization formats: JSON, XML, YAML, CSV, etc. So the code to read bounding boxes depends on the actual format of data on the disk.

After you read the data from the disk, you need to prepare bounding boxes for Albumentations.

Albumentations expects that bounding boxes will be represented as a list of lists. Each list contains information about a single bounding box. A bounding box definition should have at list four elements that represent the coordinates of that bounding box. The actual meaning of those four values depends on the format of bounding boxes (either

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

3,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

4,

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

5, or

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

6). Besides four coordinates, each definition of a bounding box may contain one or more extra values. You can use those extra values to store additional information about the bounding box, such as a class label of the object inside the box. During augmentation, Albumentations will not process those extra values. The library will return them as is along with the updated coordinates of the augmented bounding box.

Step 4. Pass an image and bounding boxes to the augmentation pipeline and receive augmented images and boxes.

As discussed in Step 2, there are two ways of passing class labels along with bounding boxes coordinates:

1. Pass class labels along with coordinates.

So, if you have coordinates of three bounding boxes that look like this:

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

you can add a class label for each bounding box as an additional element of the list along with four coordinates. So now a list with bounding boxes and their coordinates will look the following:

bboxes = [

[23, 74, 295, 388, 'dog'],
[377, 294, 252, 161, 'cat'],
[333, 421, 49, 49, 'sports ball'],
]

or with multiple labels per each bounding box:

bboxes = [

[23, 74, 295, 388, 'dog', 'animal'],
[377, 294, 252, 161, 'cat', 'animal'],
[333, 421, 49, 49, 'sports ball', 'item'],
]

You can use any data type for declaring class labels. It can be string, integer, or any other Python data type.

Next, you pass an image and bounding boxes for it to the

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

07 function and receive the augmented image and bounding boxes.

transformed = transform(image=image, bboxes=bboxes) transformed_image = transformed['image'] transformed_bboxes = transformed['bboxes']

Convert x y w h to top left right bottom
Example input and output data for bounding boxes augmentation

2. Pass class labels in a separate argument to

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

07 (the preferred way).

Let's say you have coordinates of three bounding boxes

bboxes = [

[23, 74, 295, 388],
[377, 294, 252, 161],
[333, 421, 49, 49],
]

You can create a separate list that contains class labels for those bounding boxes:

class_labels = ['cat', 'dog', 'parrot']

Then you pass both bounding boxes and class labels to

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

07. Note that to pass class labels, you need to use the name of the argument that you declared in

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

08 when creating an instance of Compose in step 2. In our case, we set the name of the argument to

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

18.

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

0

Convert x y w h to top left right bottom
Example input and output data for bounding boxes augmentation with a separate argument for class labels

Note that

transform = A.Compose([

A.RandomCrop(width=450, height=450),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco'))

08 expects a list, so you can set multiple fields that contain labels for your bounding boxes. So if you declare Compose like

How to convert bounding box x1 y1 x2 y2 to yolo style?

YOLO normalises the image space to run from 0 to 1 in both x and y directions. To convert between your (x, y) coordinates and yolo (u, v) coordinates you need to transform your data as u = x / XMAX and y = y / YMAX where XMAX , YMAX are the maximum coordinates for the image array you are using.

What is Xyxy format?

'xyxy': boxes are represented via corners, x1, y1 being top left and x2, y2 being bottom right. This is the format that torchvision utilities expect. 'xywh' : boxes are represented via corner, width and height, x1, y2 being top left, w, h being width and height.

How do you normalize a bounding box coordinate?

To normalize, the x coordinate of the center by the width of the image and the y coordinate of the center by the height of the image. The values of width and height are also normalized. In the Pascal format, the bounding box is represented by the top-left and bottom-right coordinates.

What is the formula for Yolo format?

yolo. In yolo , a bounding box is represented by four values [x_center, y_center, width, height] . x_center and y_center are the normalized coordinates of the center of the bounding box. To make coordinates normalized, we take pixel values of x and y, which marks the center of the bounding box on the x- and y-axis.