-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Add support for custom classes #71
Add support for custom classes #71
Conversation
Codecov Report
@@ Coverage Diff @@
## master #71 +/- ##
==========================================
+ Coverage 82.20% 82.28% +0.07%
==========================================
Files 84 84
Lines 3974 4013 +39
Branches 614 629 +15
==========================================
+ Hits 3267 3302 +35
- Misses 576 577 +1
- Partials 131 134 +3
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Hi @igonro |
Is that functionality already being implemented? If not, I could try to implement it. @xvjiarui |
Hi @igonro |
Have you identified any problem or any way to proceed to implement it? I'm still a newbie to mmsegmentation, so it would be great to get some hint (if you have thought about it). @xvjiarui |
Hi @xvjiarui, can you check out the last changes I have made? |
mmseg/datasets/custom.py
Outdated
@@ -160,6 +187,8 @@ def get_ann_info(self, idx): | |||
def pre_pipeline(self, results): | |||
"""Prepare results dict for pipeline.""" | |||
results['seg_fields'] = [] | |||
if self.custom_classes: | |||
results['old_id_to_new_id'] = self.old_id_to_new_id |
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.
Could we use something like label_map
and add some comments about it?
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 don't understand what you mean by label_map
. Do you mean changing the key name?
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.
Sorry for the ambiguity.
Yes, 'old_id_to_new_id'
is a bit too long. But 'label_map'
may not be straight forward enough. Any idea?
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.
Maybe class_transform
, class_id_transform
or label_transform
?
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.
Or label_map
could be good with a comment explaining it.
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.
Then label_map
it is. We may add comments about key and value of this dict.
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.
We may also add comments about what's the purpose of adding this dict.
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 shall we rename it to label_map
?
mmseg/datasets/custom.py
Outdated
if matched_classes < len(classes): | ||
raise ValueError('classes is not a subset of CLASSES.') |
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.
We may check this by python builtin issubset
.
mmseg/datasets/custom.py
Outdated
self.old_id_to_new_id = {} | ||
matched_classes = 0 | ||
for i, c in enumerate(self.CLASSES): | ||
if c not in classes: |
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.
We may remove this condition by checking issubset
first.
mmseg/datasets/custom.py
Outdated
def get_palette_for_custom_classes(self, palette=None): | ||
|
||
if palette: | ||
if isinstance(palette, str): | ||
# take it as a file path | ||
palette_values = mmcv.list_from_file(palette) | ||
elif isinstance(palette, (tuple, list)): | ||
palette_values = palette | ||
else: | ||
raise ValueError( | ||
f'Unsupported type {type(palette)} of palette.') | ||
|
||
else: | ||
palette_values = [] | ||
for x in sorted(self.old_id_to_new_id.items(), key=lambda x: x[1]): | ||
if x[1] != -1: | ||
palette_values.append(self.PALETTE[x[0]]) | ||
|
||
palette_values = type(self.PALETTE)(palette_values) | ||
|
||
return palette_values |
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.
Custom palette from user input may not be necessary for CustomDataset
. We may directly set palette
by indices from subclasses.
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.
Yes, sorry. I was still fixing some things... You can now take a look if you can.
classes=None, | ||
test_mode=True) | ||
|
||
assert custom_dataset.CLASSES == original_classes |
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.
We may add a test case for LoadAnnotation
pipeline when there is custom classes.
To achieve this, we may generate a random ground truth segmentation map.
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 I add it in test_loading.py
or in this same file? Also I'm not very sure what type of test I should add.
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.
We may add it in test_loading.py
.
We should check if the loaded annotation is of custom classes as desired.
You may change the draft status when this PR is ready. |
mmseg/datasets/custom.py
Outdated
if palette: | ||
if isinstance(palette, str): | ||
# take it as a file path | ||
palette = mmcv.list_from_file(palette) |
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.
The palette
is a list of list. It is not trivial to load palette from path.
I suggest removing this function. We just need to select the right palette
if there is.
tests/test_data/test_loading.py
Outdated
test_gt[6:8, 2:4] = 3 | ||
test_gt[6:8, 6:8] = 4 | ||
|
||
img_path = osp.join(osp.dirname(__file__), 'img.jpg') |
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've tried using tmpdir
and tmp_path
for doing this, but it raises an error when calling imwrite
(not sure why), so I've had to make this workaround.
Hey @xvjiarui, could you review this when you have the time? Thanks! |
Hi @igonro Update: |
Fixed. I've missunderstood your comment. |
mmseg/datasets/custom.py
Outdated
reduce_zero_label=False): | ||
reduce_zero_label=False, | ||
classes=None, | ||
palette=None): |
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.
palette
arg is not needed.
mmseg/datasets/custom.py
Outdated
@@ -230,6 +244,49 @@ def get_gt_seg_maps(self): | |||
|
|||
return gt_seg_maps | |||
|
|||
def get_classes_and_palette(self, classes=None, palette=None): |
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.
palette
arg is not needed.
else: | ||
self.label_map[i] = classes.index(c) | ||
|
||
return class_names, palette |
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.
We need to return the subset of PALETTE
since we are using a subset of CLASSES
.
Hi @igonro |
…segmentation into add-support-for-custom-classes
Hi @xvjiarui |
* Support for custom classes * Fix test * Fix pre-commit * Add pipeline logic for custom classes * Fix minor issues, fix test * Fix issues from PR review * Fix tests * Remove palette as str * Rename old_to_new_ids to label_map * Test for load_anns * Remove get_palette function * fixed temp * Add subset of palette, remove palette as arg * minor update Co-authored-by: Jiarui XU <xvjiarui0826@gmail.com>
* refactor fir up/down sample * remove variance scaling * remove variance scaling from unet sde * refactor Linear * style * actually remove variance scaling * add back upsample_2d, downsample_2d * style * fix FirUpsample2D
Please, read open-mmlab/mmdetection#2408 for understanding the changes and the justification.
I didn't add the boolean parameter
custom_classes
(as it is currently in mmdetection), because I didn't know if it would fit or if it would be necessary to do it. Everything else has been done with the intention of following the logic as it is in mmdetection.