Skip to content

Commit

Permalink
Patch 4: Docs, Improvements, Bug fixes (#4)
Browse files Browse the repository at this point in the history
- Refactored major sections of `pybx.basics` and the `BxType` 
- Backwards incompatible!
- Detailed docstrings for all methods and classes
- Directly visualize arrays in `VisBx()`
- Visualize, iterate, `__add__` operations for `BaseBx`
- Helper function to set and return BxType (`get_bx`)
- Several verbal assertions and bug fixes
- Fixes #3 #2 
- [dev] Updated tests
  • Loading branch information
thatgeeman authored Jan 20, 2022
1 parent 5273ae5 commit f0a149e
Show file tree
Hide file tree
Showing 14 changed files with 565 additions and 202 deletions.
16 changes: 16 additions & 0 deletions data/annots_key.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"x_min": 50.0,
"y_min": 70.0,
"x_max": 120.0,
"y_max": 100.0,
"class": "person"
},
{
"x_min": 150.0,
"y_min": 200.0,
"x_max": 250.0,
"y_max": 240.0,
"class": 4
}
]
Binary file modified data/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 12 additions & 17 deletions src/pybx/anchor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@


def get_edges(image_sz: tuple, feature_sz: tuple, op='noop'):
"""
generate offsetted top (x_min, y_min) or bottom edges (x_max, y_max)
"""Generate offsetted top `(x_min, y_min)` or bottom edges `(x_max, y_max)`
coordinates of a given feature size based on op.
if op is noop, gets the top edges.
if op is add, gets the bottom edges.
if `op` is `noop`, gets the top edges.
if `op` is `add`, gets the bottom edges.
:param op: operation for calculating edges, either 'add' 'sub' 'noop'
:param image_sz: tuple of (width, height, channels) of an image
:param feature_sz: tuple of (width, height) of a channel
:param image_sz: tuple of `(W, H, C)` of an image
:param feature_sz: tuple of `(W, H)` of a channel
:return: offsetted edges of each feature
"""
assert image_sz[-1] < image_sz[0], f'expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
assert len(image_sz) == 3, f'expected image_sz of len 3, got {len(image_sz)}'
assert op in __ops__, f'operator not in allowed operations: {__ops__}'
assert image_sz[-1] < image_sz[0], f'{__name__}: Expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
assert len(image_sz) == 3, f'{__name__}: Expected image_sz of len 3, got {len(image_sz)}'
assert op in __ops__, f'{__name__}: Operator not in allowed operations: {__ops__}'
w, h, _ = image_sz
nx, ny = feature_sz
diag_edge_ofs = w / nx, h / ny
Expand All @@ -31,8 +30,7 @@ def get_edges(image_sz: tuple, feature_sz: tuple, op='noop'):


def bx(image_sz: tuple, feature_sz: tuple, asp_ratio: float = None, clip=True, named=True, anchor_sfx: str = 'a'):
"""
calculate anchor box coords given an image size and feature size for a single aspect ratio
"""Calculate anchor box coords given an image size and feature size for a single aspect ratio.
:param image_sz: tuple of (width, height) of an image
:param feature_sz: tuple of (width, height) of a channel
:param asp_ratio: aspect ratio (width:height)
Expand All @@ -41,7 +39,7 @@ def bx(image_sz: tuple, feature_sz: tuple, asp_ratio: float = None, clip=True, n
:param anchor_sfx: suffix for anchor label: anchor_sfx_asp_ratio_feature_sz
:return: anchor box coordinates in [pascal_voc] format
"""
assert image_sz[-1] < image_sz[0], f'expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
assert image_sz[-1] < image_sz[0], f'{__name__}: Expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
_max = max(image_sz[0], image_sz[1])
asp_ratio = 1. if asp_ratio is None else asp_ratio
# n_boxes = __mul__(*feature_sz)
Expand All @@ -54,8 +52,6 @@ def bx(image_sz: tuple, feature_sz: tuple, asp_ratio: float = None, clip=True, n
_w = coords_wh[:, 0] * math.sqrt(asp_ratio)
_h = coords_wh[:, 1] / math.sqrt(asp_ratio)
coords_asp_wh = np.stack([_w, _h], -1)
# TODO: given the center, any format for the anchors can be obtained
# TODO: validate with box iou of coords and given bounding box
xy_min = coords_center - coords_asp_wh / 2
xy_max = coords_center + coords_asp_wh / 2
coords = np.hstack([xy_min, xy_max])
Expand All @@ -67,15 +63,14 @@ def bx(image_sz: tuple, feature_sz: tuple, asp_ratio: float = None, clip=True, n


def bxs(image_sz, feature_szs: list = None, asp_ratios: list = None, named: bool = True, **kwargs):
"""
calculate anchor box coords given an image size and multiple feature sizes for mutiple aspect ratios
"""Calculate anchor box coords given an image size and multiple feature sizes for mutiple aspect ratios.
:param image_sz: tuple of (width, height) of an image
:param feature_szs: list of feature sizes for anchor boxes, each feature size being a tuple of (width, height) of a channel
:param asp_ratios: list of aspect rations for anchor boxes, each aspect ratio being a float calculated by (width:height)
:param named: whether to return (coords, labels)
:return: anchor box coordinates in [pascal_voc] format
"""
assert image_sz[-1] < image_sz[0], f'expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
assert image_sz[-1] < image_sz[0], f'{__name__}: Expected {image_sz[-1]} < {image_sz[0]}={image_sz[1]}'
asp_ratios = [1 / 2., 1., 2.] if asp_ratios is None else asp_ratios
feature_szs = [(8, 8), (2, 2)] if feature_szs is None else feature_szs
# always named=True for bx() call. named=True in fn signature of bxs() is in its scope.
Expand Down
Loading

0 comments on commit f0a149e

Please sign in to comment.