Parsing Cheatsheet
The goal is to create a resource that will help both beginners and advanced users to easily create their parsers by providing some frequently used code snippets and best practices
Useful example
Use template generator
The IceVision template generator helps you to generate all the methods that you need to implement based on the parsers mixins. The first step is to create a class that inherits from these smaller building blocks called mixins:
Mixins
This is just an example, choose the mixins that are relevant to your use case.
class WheatParser(parsers.FasterRCNN, parsers.FilepathMixin, parsers.SizeMixin):
pass
generate_template
that will print out all the necessary methods we have to implement.
WheatParser.generate_template()
Output:
def __iter__(self) -> Any:
def height(self, o) -> int:
def width(self, o) -> int:
def filepath(self, o) -> Union[str, Path]:
def bboxes(self, o) -> List[BBox]:
def labels(self, o) -> List[int]:
def record_id(self, o) -> Hashable:
If, for example, all the images are .jpg
and located in the data_dir
folder, the image_paths
attribute will be set as follow:
def __init__(self, data_dir):
self.image_paths = get_files(data_dir, extensions=[".jpg"])
Files code snippets
Let's suppose we have the follwoing fname
variable:
fname = Path("PennFudanPed/PNGImages/FudanPed00002.png")
fname | PennFudanPed/PNGImages/FudanPed00002.png |
---|---|
fname.exists() | True |
fname.with_suffix('.txt') | PennFudanPed/PNGImages/FudanPed00002.txt |
fname.stem | FudanPed00002 |
Parsing code snippets
Read a CSV file using pandas
import pandas as pd
df = pd.read_csv("path/to/csv/file")
df.head() # or df.sample()
Example of parsing bboxes attributes defined as an array, and stored in a string:
bbox = "[834.0, 222.0, 56.0, 36.0]"`
xywh = np.fromstring(bbox[1:-1], sep=",")
print(xywh)
array([834., 222., 56., 36.])
Example of parsing bboxes attributes defined as a string with a blank separator
label = "2 0.527267 0.702972 0.945466 0.467218"
xywh = np.fromstring(label, sep=" ")[1:]
print(xywh)
array([0.527267, 0.702972, 0.945466, 0.467218])
Masks
Let's assume we have the following dictionnary entries to parse in order to create the corresponding masks. Check out the full dictionnary annotations.json
"annotations": [
{
"segmentation": [
[457.3, 258.92, 458.38, 276.22, 467.03, 289.19, 473.51, 305.41, 483.24, 334.59,...]
],
"area": 43522.80595,
"iscrowd": 0,
"image_id": 343934,
"bbox": [
175.14,
175.68,
321.08,
240
],
"category_id": 4,
"id": 150977
},
{
"segmentation": [
[507.9, 413.08, ...]
...
}
...
]
We can implement the abstract method masks()
, defined in the abstract class MasksMixin
that is inhereted by the MaskRCNN
class (see parsers documentation), as follow:
class COCOAnnotationParser(MaskRCNN, COCOBBoxParser):
def masks(self, o) -> List[MaskArray]:
seg = o["segmentation"]
if o["iscrowd"]:
return [RLE.from_coco(seg["counts"])]
else:
return [Polygon(seg)]