PyPI version Open In Collab

A simple python package to generate anchor boxes for multi-box object detection models.

Calculated anchor boxes are in pascal_voc format by default.

Installation

pip install pybx

Usage

To calculate the anchor boxes for a single feature size and aspect ratio, given the image size:

from pybx import anchor, ops

image_sz = (300, 300)
feature_sz = (10, 10)
asp_ratio = 1/2.

coords, labels = anchor.bx(image_sz, feature_sz, asp_ratio)

100 anchor boxes of asp_ratio 0.5 is generated along with unique labels:

len(coords), len(labels)
(100, 100)

The anchor box labels are especially useful, since they are pretty descriptive:

coords[-1], labels[-1]
([274.3933982822018, 263.7867965644036, 295.6066017177982, 300.0],
 'a_10x10_0.5_99')

To calculate anchor boxes for multiple feature sizes and aspect ratios, we use anchor.bxs instead:

feature_szs = [(10, 10), (8, 8)]
asp_ratios = [1., 1/2., 2.]

coords, labels = anchor.bxs(image_sz, feature_szs, asp_ratios)

All anchor boxes are returned as ndarrays of shape (N,4) where N is the number of boxes.

The box labels are even more important now, since they help you uniquely identify to which feature map size or aspect ratios they belong to.

coords[101], labels[101]
(array([34.39339828,  0.        , 55.60660172, 36.21320344]), 'a_10x10_0.5_1')
coords[-1], labels[-1]
(array([254.73349571, 267.99174785, 300.        , 294.50825215]),
 'a_8x8_2.0_63')

MultiBx methods

Box coordinates (with/without labels) in any format (usually ndarray, list, json, dict) can be instantialized as a MultiBx, exposing many useful methods and attributes of MultiBx. For example to calculate the area of each box iteratively:

from pybx.basics import * 
# passing anchor boxes and labels from anchor.bxs()
print(coords.shape)

boxes = mbx(coords, labels)
type(boxes)
(492, 4)
pybx.basics.MultiBx
len(boxes)
492
areas = [b.area for b in boxes]

Each annotation in the MultiBx object boxes is also a BaseBx with its own set of methods and properties.

boxes[-1]
BaseBx(coords=[[254.73349570550448, 267.9917478527522, 300.0, 294.5082521472478]], label=['a_8x8_2.0_63'])
boxes[-1].coords, boxes[-1].label
((#1) [[254.73349570550448, 267.9917478527522, 300.0, 294.5082521472478]],
 (#1) ['a_8x8_2.0_63'])

MultiBx objects can also be “added” which stacks them vertically to create a new MultiBx object:

boxes_true = mbx(coords_json)    # annotation as json records
len(boxes_true)
2
boxes_anchor = mbx(coords_numpy) # annotation as ndarray
len(boxes_anchor)
492
boxes_true
MultiBx(coords=[[150, 70, 270, 220], [10, 180, 115, 260]], label=['clock', 'frame'])
boxes = boxes_true + boxes_anchor + boxes_true
len(boxes)
496