voxel51 / fiftyone

The open-source tool for building high-quality datasets and computer vision models
https://fiftyone.ai
Apache License 2.0
8.09k stars 537 forks source link

[?] Confusion on how map_labels() works #4228

Open GilSeamas opened 5 months ago

GilSeamas commented 5 months ago

PROBLEM

map_labels method does not make mapping one by one, basically there is this mapping:

for example:

HUMAN: None HUMAN_IN_STREET: HUMAN HUMAN_IN_CAR: None HUMAN_IN_BUILDING: None

Our database has a problem which has HUMAN label for objects that are not HUMAN_IN_STREET, but rather humans in places like CAR and BUILDING, which we are not interested in detecting.

We make the mapping above to solve that.

However, map_labels returns the following mapping

HUMAN: None HUMAN_IN_STREET: None HUMAN_IN_CAR: None HUMAN_IN_BUILDING: None

since HUMAN_IN_STREET is mapped to HUMAN, and HUMAN mapped to None, in the end HUMAN_IN_STREET: None

Code to reproduce issue

    with open("./yolov5/data/class_map.yaml", "r") as f:
        class_map = yaml.load(f, Loader=yaml.FullLoader)

    view = view.map_labels("ground_truth_det", class_map)

this is not necesserily a bug, because this use case is very specific but I guess this is not the expected behaviour and maybe yout would like to take a look

best regards, Gil

swheaton commented 5 months ago

Thanks for the report @GilSeamas I'm not able to reproduce this with the below code. I can't use your reproducing code because I don't know what the view is or have the class_map.yaml file, etc.

import fiftyone as fo

ds = fo.Dataset()
ds.add_samples(
    [
        fo.Sample(
            filepath="/path/to/image1.png",
            ground_truth=fo.Detections(
                detections=[
                    fo.Detection(label="HUMAN"),
                    fo.Detection(label="HUMAN_IN_STREET"),
                ]
            ),
        ),
        fo.Sample(
            filepath="/path/to/image2.png",
            ground_truth=fo.Detections(
                detections=[
                    fo.Detection(label="HUMAN_IN_CAR"),
                    fo.Detection(label="HUMAN_IN_BUILDING"),
                ]
            ),
        ),
    ]
)
assert ds.values("ground_truth.detections.label") == [
    ['HUMAN', 'HUMAN_IN_STREET'],
    ['HUMAN_IN_CAR', 'HUMAN_IN_BUILDING']
]
mapping = {
    "HUMAN": None,
    "HUMAN_IN_STREET": "HUMAN",
    "HUMAN_IN_CAR": None,
    "HUMAN_IN_BUILDING": None,
}
view = ds.map_labels("ground_truth", mapping)
assert view.values("ground_truth.detections.label") == [
    [None, 'HUMAN'],
    [None, None]
]