I’d like to apply a custom transformation to image data and train a network to undo it. I plan to use a given image as its own output, and apply my transformation on the input side.
One ugly way to implement this would be to subclass
ImageItemList for the input and override
.get, applying my transformation to
Image.data before returning it. I’d rather learn to do this kind of thing the right way.
It seems easy enough to make a function into a transform (
mytfm = Transform(func)), but now how does the transform get in the queue? I tried calling
get_transforms, appending my transform to each list, and then passing those lists to an
ImagedataBunch instantiation method (
.apply_tfms(mytfm) fails whenever I try to work with a datapoint, due to the expectation that
mytfm has a
.tfm attribute, which suggests
im.apply_tfms expects a
RandTransform or some other similar wrapper as input (even though the argument
tfms is typed as
TfmList which includes callables).
I also tried calling
DataBunch.add_tfm with the same result – it wants a
Transform wrapped so that it has a
The next step would be to wrap my function in a
RandTransform, but this still seems wrong, since my transformation is deterministic and not designed for data augmentation, it’s pre-processing for the input data.
Another fix would be to create a generic wrapper with the required attribute, but it seems strange that such a thing doesn’t already exist? Maybe I’m overlooking it, but I would have expected
RandTransform to be a subclass of the generic wrapper class.
I’m also looking at all the
.process methods in
data_block, but I think these use instances of
PreProcessor, which as I understand get applied at the
ImageItemList.items level, which in my case is an array of Path objects - the
Image object only gets loaded when used.
What is the usual way of working with a custom transform?