Package: pybboxes
PyBboxesLight weight toolkit for bounding boxes providing conversion between bounding box types and simple computations. Supported bounding box types (italicized text indicates normalized values):albumentations:Albumentations Format[x-tl, y-tl, x-br, y-br](Normalized VOC Format) Top-left coordinates & Bottom-right coordinatescoco:COCO (Common Objects in Context)[x-tl, y-tl, w, h]Top-left corner & width & heightfiftyone:FiftyOne[x-tl, y-tl, w, h](Normalized COCO Format) Top-left coordinates & width & heightvoc:Pascal VOC[x-tl, y-tl, x-br, y-br]Top-left coordinates & Bottom-right coordinatesyolo:YOLO[x-c, y-c, w, h]Center coordinates & width & heightGlossarytl:top-leftbr:bottom-righth:heightw:widthc:centerImportant NoticeSupport for Python<3.8 will be dropped starting version0.2though the development for Python3.6 and Python3.7 may
continue where it will be developed under version0.1.xfor future versions. This may introduce; however, certain
discrepancies and/or unsupported operations in the0.1.xversions. To fully utilize and benefit from the entire
package, we recommend using Python3.8 at minimum (Python>=3.8).InstallationThrough pip (recommended),pip install pybboxesor build from source,git clone https://github.com/devrimcavusoglu/pybboxes.git
cd pybboxes
python setup.py installBounding BoxesYou can easily create bounding box as easy asfrompybboxesimportBoundingBoxmy_coco_box=[98,345,322,117]coco_bbox=BoundingBox.from_coco(*my_coco_box)# <[98 345 322 117] (322x117) | Image: (?x?)># or alternatively# coco_bbox = BoundingBox.from_array(my_coco_box)Out of Bounds BoxesPybboxes supports OOB boxes, there exists a keywordstrictin both Box classes (construction) and in functional
modules. Whenstrict=True, it does not allow out-of-bounds boxes to be constructed and raises an exception, while
it does allow out-of-bounds boxes to be constructed and used whenstrict=False. Also, there is a propertyis_oobthat indicates whether a particular bouding box is OOB or not.ImportantNote that, if the return value foris_oobisNone, then it indicates that OOB status is unknown
(e.g. image size required to determine, but not given). Thus, valuesNoneandFalseindicates different information.frompybboxesimportBoundingBoximage_size=(640,480)my_coco_box=[98,345,580,245]# OOB box for 640x480coco_bbox=BoundingBox.from_coco(*my_coco_box,image_size=image_size)# Exception# ValueError: Given bounding box values is out of bounds. To silently skip out of bounds cases pass 'strict=False'.coco_bbox=BoundingBox.from_coco(*my_coco_box,image_size=image_size,strict=False)# No Exceptioncoco_bbox.is_oob# TrueIf you want to allow OOB, but still check OOB status, you should usestrict=Falseandis_oobwhere needed.ConversionWith theBoundingBoxclass the conversion is as easy as one method call.frompybboxesimportBoundingBoxmy_coco_box=[98,345,322,117]coco_bbox=BoundingBox.from_coco(*my_coco_box)# <[98 345 322 117] (322x117) | Image: (?x?)>voc_bbox=coco_bbox.to_voc()# <[98 345 420 462] (322x117) | Image: (?x?)>voc_bbox_values=coco_bbox.to_voc(return_values=True)# (98, 345, 420, 462)However, if you try to make conversion between two bounding boxes that require scaling/normalization it'll give an errorfrompybboxesimportBoundingBoxmy_coco_box=[98,345,322,117]coco_bbox=BoundingBox.from_coco(*my_coco_box)# <[98 345 322 117] (322x117) | Image: (?x?)># yolo_bbox = coco_bbox.to_yolo()  # this will raise an exception# You need to set image_size for coco_bbox and then you're good to gococo_bbox.image_size=(640,480)yolo_bbox=coco_bbox.to_yolo()# <[0.4047 0.8406 0.5031 0.2437] (322x117) | Image: (640x480)>Image size associated with the bounding box can be given at the instantiation or while using classmethods e.gfrom_coco().frompybboxesimportBoundingBoxmy_coco_box=[98,345,322,117]coco_bbox=BoundingBox.from_coco(*my_coco_box,image_size=(640,480))# <[98 345 322 117] (322x117) | Image: (640x480)># no longer raises exceptionyolo_bbox=coco_bbox.to_yolo()# <[0.4047 0.8406 0.5031 0.2437] (322x117) | Image: (640x480)>Box operationsBox operations now available as ofv0.1.0.frompybboxesimportBoundingBoxmy_coco_box=[98,345,322,117]my_coco_box2=[90,350,310,122]coco_bbox=BoundingBox.from_coco(*my_coco_box,image_size=(640,480))coco_bbox2=BoundingBox.from_coco(*my_coco_box2,image_size=(640,480))iou=coco_bbox.iou(coco_bbox2)# 0.8117110631149508area_union=coco_bbox+coco_bbox2# 41670 | alternative way: coco_bbox.union(coco_bbox2)total_area=coco_bbox.area+coco_bbox2.area# 75494  (not union)intersection_area=coco_bbox*coco_bbox2# 33824 | alternative way: coco_bbox.intersection(coco_bbox2)first_bbox_diff=coco_bbox-coco_bbox2# 3850second_bbox_diff=coco_bbox2-coco_bbox# 3996bbox_ratio=coco_bbox/coco_bbox2# 0.9961396086726599 (not IOU)FunctionalNote: functional computations are moved underpybboxes.functionalstarting with the version0.1.0. The only
exception is thatconvert_bbox()which still can be used by importingpybboxesonly (for backward compatibility).ConversionYou are able to convert from any bounding box type to another.importpybboxesaspbxcoco_bbox=(1,2,3,4)# COCO Format bbox as (x-tl,y-tl,w,h)voc_bbox=(1,2,3,4)# Pascal VOC Format bbox as (x-tl,y-tl,x-br,y-br)pbx.convert_bbox(coco_bbox,from_type="coco",to_type="voc")# (1, 2, 4, 6)pbx.convert_bbox(voc_bbox,from_type="voc",to_type="coco")# (1, 2, 2, 2)Some formats require image width and height information for scaling, e.g. YOLO bbox (resulting coordinates
are rounded to 2 decimals to ease reading).importpybboxesaspbxvoc_bbox=(1,2,3,4)# Pascal VOC Format bbox as (x-tl,y-tl,x-br,y-br)pbx.convert_bbox(voc_bbox,from_type="voc",to_type="yolo",image_size=(28,28))# (0.07, 0.11, 0.07, 0.07)ComputationYou can also make computations on supported bounding box formats.importpybboxes.functionalaspbfcoco_bbox=(1,2,3,4)# COCO Format bbox as (x-tl,y-tl,w,h)voc_bbox=(1,2,3,4)# Pascal VOC Format bbox as (x-tl,y-tl,x-br,y-br)pbf.compute_area(coco_bbox,bbox_type="coco")# 12pbf.compute_area(voc_bbox,bbox_type="voc")# 4ContributingInstallationInstall the package as follows, which will set you ready for the development mode.pipinstall-e.[dev]TestsTo tests simply run.python tests/run_tests.pyCode StyleTo check code style,python tests/run_code_style.py checkTo format codebase,python tests/run_code_style.py formatLicenseLicensed under theMITLicense.