Custom data block, item_tfms not being applied

Hello,

I am trying to build a custom data block like in the siamese tutorial.
The core part of the code:

> def TileImageBlock(): 
>     print('TileImageBlock')
>     return TransformBlock(type_tfms=TileImage.create, batch_tfms=IntToFloatTensor)
> 
> class TileImage(fastuple):
>     '''
>     This class creates a TensorImage from a wsi_processing_pipeline.shared.tiles.Tile object.
>     additionally the show method enables to display the Tile object as an image
>     '''
>     @classmethod
>     def create(cls, t:shared.tile.Tile, **kwargs):
>         print('TileImage.create')
>         if not isinstance (t, shared.tile.Tile):
>             raise ValueError(f'{type(t)} not supported')
>         
>         return fastai.vision.core.PILImage.create(t.get_np_tile())            

data block api:

> final_size = 512
> bs = 2
> 
> data = fastai.data.block.DataBlock(
>         blocks=(ImageBlock, fastai.data.block.MultiCategoryBlock),
>         get_x=lambda x: x, 
>         get_y=lambda x: x.get_labels(),
>         splitter=fastai.data.transforms.FuncSplitter(lambda x: x.get_dataset_type() == shared.enums.DatasetType.validation),
>         item_tfms = fastai.vision.augment.Resize(size=final_size, method = 'squish'),
>         batch_tfms=fastai.vision.augment.aug_transforms(flip_vert=True))
> 
> dls = data.dataloaders(patient_manager.get_all_tiles(), bs=bs)      

A Tile object just represents a tile in a whole-slide image and it “knows” how to extract a pil or numpy image from the whole-slide image. That way I can extract the tiles during dataloading without the necessity to extract and save them to disc and wasting a lot of time and space.

So essentially the only difference to a “normal” image classification task is the way the image is opened.
It is not opened from a given path but extracted from a whole-slide image. From that point on everything is the same.

The problem I am facing now is, that the item transforms are not applied by the dataloader.
The images in the dataloaders are not resized to 512x512 but remain the original size.
The batch transforms are applied though.
I have already found this post, but it did not really help me.
https://forums.fast.ai/t/item-tfms-not-being-applied-for-custom-imageblock-class/69352

Resize.encode’s
declaration and type hinting shows that it can handle the following types:
x:(Image.Image,TensorBBox,TensorPoint)
I already tried to return a plain PIL.Image.Image in the TileImage.create method, but that did not work and
the dataloader could not even be built properly without a mistake.
That’s why I tried the fastai.vision.core.PILImage class instead like the standard ImageBlock uses.
Now the dataloader is built and the batch_tfms are applied, but not the resizing.

What am I missing, so that the item transforms and especially the resizing takes effect.

Thanks in advance!

Christoph

@florianl provided the answer to this one here: Interest in multispectral/satellite images?

In short, you need to write not only a class for the TileImage and TileImageBlock, but also custom classes for the transforms, e.g., TileCropPad, etc.

Thanks a lot. I simply made a very stupid mistake.
The problem was, I checked the shape of the output in the wrong place.
I checked it here: dls.train_ds[0][0].shape
But of couse the resizing has not been applied at this stage.
(dls.train_ds[0][0].shape shows that the resizing is applied)