Using fastai for Segmentation, receiving a CUDA device-side assertion error

Thanks, it appears to be that, do you know why open_image does that [0,255] instead of 0,1? My images are saved as 1bit with PIL.
This solved the issue:

class MySegmentationLabelList(SegmentationLabelList):
  def open(self, fn): return open_mask(fn, div=True)

class MySegmentationItemList(ImageItemList):
    "`ItemList` suitable for segmentation tasks."
    _label_cls,_square_show_res = MySegmentationLabelList,False
2 Likes

It depends on how your masks are encoded I guess.

Can you also show how you use those classes to create databunch?

I am trying to solve this problem, any tips on how I could get good segmentation masks?

  src = (MySegmentationItemList.from_folder(path_img)
       .random_split_by_pct(.2)
       .label_from_func(get_y_fn, classes=['background','solar_module']))
  data = (src.transform(get_transforms(), size=size, tfm_y=True)
        .databunch(bs=bs)
        .normalize(imagenet_stats))

[quote=ā€œsgugger, post:3, topic:30292ā€]
Not that any time you get a CUDA error, you have to rest
[/quote]But I use:mask = open_mask(get_y_fn(img_f), div=True)
mask.show(figsize=(5,5), alpha=1)
, then the mask shows all black. No mask now, right?

My images are .jpg, masks are .png, I tried mask.data[0][50][20:600] to see the data, and found lots of values are 38, the others are 0

If itā€™s a binary task and you have values of 38 and 0, you must divide by 38 your images or set every value greater than 0 to 1, for example hereā€™s some code tha I use in a similar case:

def open_mk(fn:PathOrStr, div:bool=False, convert_mode:str='L', cls:type=ImageSegment,
        after_open:Callable=None)->Image:
    "Return `Image` object created from image in file `fn`."
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", UserWarning) # EXIF warning from TiffPlugin
        x = PIL.Image.open(fn).convert(convert_mode)
    if after_open: x = after_open(x)
    x = pil2tensor(x,np.float32)
    x[x>0]=1  #MODIFIDED
    if div: x.div_(255)
    return cls(x)

class CustomSegmentationLabelList(SegmentationLabelList):
    def open(self,fn): return open_mk(fn)
    
class CustomSegmentationItemList(ImageList):
    _label_cls= CustomSegmentationLabelList
2 Likes

For all segmentation tasks, make sure that your labels are always starting at 0 and increasing till the number of classes minus 1. For 10 classes your labels should be 0,ā€¦,9.

Best is preprocessing the masks and saving the correct format on disk. Best use ImageJ / Fiji for this task, then you can also check that everything fits. Sure you can do it with python, but transforming your data on the fly when loading it for learning is too resource intense, so I would not do that.

@alex_zhang has the segmentation worked for you ?

@harikrishnanrajeev Yes, I fixed it with pietro.latorreā€™s method with updated fastai, and I also added '0ā€™class to the class list, then fit_one_cycle works. Maybe I neednā€™t generat the mask, but just load from coco json file, I havenā€™t tried that yet.

1 Like

Does anybody know why the mask shows all black ?. Is this as expected ?

1 Like

Change the displayed range to 0 ā€¦ N (where N is the number of classes).

Hey, I am also facing the same problem. I had values of 76 and 0 when i print the mask.data values. Have u found the trick how to solve. If yes please let me know.

Please have a look at the approach in this link

this works

2 Likes

thanks. it works absolutely fine.

1 Like

My brain was almost exploding because I did not find an error in my code but could not train a segmentation model. Just knowing that the accuracy metric no longer works for segmentation saved my life. Thank you.

Would be good to use DICE or even DICE + BCE . Thanks .

the problem is masks are gone .show batch and prediction doesnā€™t bring them.did u manage to solve it?

Hello,
hope thatā€™ll be useful for someoneā€¦

How I saw something wrong in my code: open_mask(ā€˜path to maskā€™).data contains values out of [0, classes-1]

2)I had mask in rle format, so I generated files with mask myself. But. I used ImageSegment.save(filename) without png format. So storing mask as png resolved my problem.

(this code from ImageSegment.save, I has copied it to my code, to add ā€˜pngā€™
x = get_image(mask, shape)
x = image2np(x.data).astype(np.uint8)
PIL.Image.fromarray(x).save(LBL_PATH/file_name,ā€˜pngā€™)

Thanks

Hi everyone,
I found this solution! Just edit the open_mask function with this partial before using SegmentationItemList, so you wonā€™t need to extend it with a custom class :slight_smile:

SegmentationItemList._label_cls.open = partial(open_mask, div=True)

2 Likes