-
Notifications
You must be signed in to change notification settings - Fork 153
Feat: MOT dataset loader #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for this PR!
Kudos for attaching such a detailed colab notebook with the PR, really helped me test the code quickly!
I have recommended some minor changes. Can you please address them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @rolson24, the PR looks good to me.
I have some minor nitpick comments.
import supervision as sv | ||
|
||
|
||
# --- Base Dataset --- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let’s remove Python comments like these; we can already tell it’s a base dataset since it only has abstract methods and implements the ABC interface.
|
||
Returns: | ||
A dictionary containing sequence information (e.g., 'frame_rate', | ||
'seqLength', 'img_width', 'img_height', 'img_dir'). Keys and value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we make sure all these dict keys follow the same naming convention? It looks like everything is in snake_case except for seqLength
. Also, wouldn’t it make more sense to use a dataclass
or a namedtuple
instead of a regular dict here?
iou_threshold: float = 0.5, | ||
remove_distractor_matches: bool = True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems that the preprocess implementation is highly dataset-specific. given that, does it really make sense to add iou_threshold
and remove_distractor_matches
to the base class, especially since there’s no guarantee they’ll be needed here? maybe it would be better to allow for additional keyword arguments instead?
|
||
|
||
# --- Base Dataset --- | ||
class EvaluationDataset(abc.ABC): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we really call this dataset EvaluationDataset
? Maybe it would make more sense to use a more general name, like TrackingDataset
or MOTDataset
instead?
logger = get_logger(__name__) | ||
|
||
|
||
def relabel_ids(detections: sv.Detections) -> sv.Detections: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Let’s rename this function from
relabel_ids
toremap_ids
. - We should also allow users to pass a custom mapping that defines how each
source_id
should be mapped to atarget_id
. - I definitely think we should add a unit test for this function.
with open(file_path, "r") as f: | ||
for line in f: | ||
line = line.strip() | ||
if not line: | ||
continue | ||
|
||
parts = line.split(",") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supervision
have a util for loading text file lines; let's use it here
# or detection confidence in det.txt | ||
confidence = float(parts[6]) | ||
|
||
class_id = int(parts[7]) if len(parts) > 7 else -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move -1
magic number to the top of the file and set is as python constant.
return sv.Detections( | ||
xyxy=xyxy, | ||
confidence=confidence, | ||
class_id=class_id, | ||
tracker_id=tracker_id, | ||
data={"frame_idx": frame_idx}, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method must return separate Detections
object per frame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So instead of storing the frame index in the data
attribute of the Detections
object, we should just return a list of Detections
objects? That probably does align more with how supervision uses Detections
objects.
logger.warning(f"No valid MOTChallenge sequences found in {self.root_path}") | ||
return sorted(sequences) | ||
|
||
def _parse_mot_file( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would need to separate loading data from file and processing data; this will allow us to unit test the data processing part
# Try common extensions explicitly if glob fails | ||
if (img_dir / f"{1:06d}.jpg").exists(): | ||
img_ext = ".jpg" | ||
elif (img_dir / f"{1:06d}.png").exists(): | ||
img_ext = ".png" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused as to how any of this would work if glob
fails.
Hi @rolson24 👋🏻 After my conversation with @soumik12345 yesterday, it became clear to me that we really need to enable benchmarking in the trackers package as soon as possible. Because of this, getting this PR over the finish line is my top priority for the week. I’ve left my comments on the PR—do you think you’ll have time to address them? If not, no worries, I can take care of it to keep things moving forward. |
Hi @SkalskiP, I can address these request these changes this weekend. Sorry I was finishing up school last week, but I should have some more time now. |
Description
This PR is the start of the evaluation framework started in #7. It contains a base dataset prototype and a MOTChallenge dataset implementation. The MOTChallenge dataset class can load, parse, preprocess, and provide an iterator for each sequence in the dataset, much in the same way TrackEval does. It also supports loading "public detections" which are pre-computed detections stored in a
dets.txt
file for each sequence which standardizes the detections that object trackers are evaluated on.Type of change
Please delete options that are not relevant.
How has this change been tested, please provide a testcase or example of how you tested the change?
Example usage:
I also have a colab notebook testing out the data loader
Any specific deployment considerations
For example, documentation changes, usability, usage/costs, secrets, etc.
Docs