<jupyter_start><jupyter_text>Vision Data> Additional helper functions to get data in a `DataLoaders` in vision applications<jupyter_code>#|hide
from nbdev.showdoc import *<jupyter_output><empty_output><jupyter_text>Batch Transforms on CPU With enough DataLoader workers and fast CPU cores, using fastai's GPU augmentations can lead to slower training then using CPU augmentations.`ImageCPUBlock` and `MaskCPUBlock` are convenience methods for executing fastai batch transforms on CPU.  CPU Batch Transform Helpers -<jupyter_code>#|export
class PreBatchAsItem(DisplayedTransform):
    "Converts Tensor from CHW to BCHW by adding a fake B dim"
    order=11
    def encodes(self, x:TensorImage|TensorMask|TensorPoint|TensorBBox):
        return x.unsqueeze(0)
    def decodes(self, x:TensorImage|TensorMask|TensorPoint|TensorBBox):
        return x.squeeze(0)
#|export
class PostBatchAsItem(DisplayedTransform):
    "Converts Tensor from BCHW to CHW by removing the fake B dim"
    order=98
    def encodes(self, x:TensorImage|TensorMask|TensorPoint|TensorBBox):
        return x.squeeze(0)
    def decodes(self, x:TensorImage|TensorMask|TensorPoint|TensorBBox):
        return x.unsqueeze(0)<jupyter_output><empty_output><jupyter_text>PyTorch 2D image transforms expect tensors to be in BCHW format. `PreBatchAsItem` and `PostBatchAsItem` add and remove a B dim to a single Tensor Image so fastai batch transforms will work on individual items.  CPU Batch Blocks -<jupyter_code>#|export
def ImageCPUBlock(cls:PILBase=PILImage):
    "A `TransformBlock` for images of `cls` for running batch_tfms on CPU"
    return TransformBlock(type_tfms=cls.create, 
                          item_tfms=[IntToFloatTensor, PreBatchAsItem, PostBatchAsItem])
#|export
def MaskCPUBlock(codes:listy|None=None):
    "A `TransformBlock` for segmentation masks, potentially with `codes`, for running batch_tfms on CPU"
    return TransformBlock(type_tfms=PILMask.create, 
                          item_tfms=[AddMaskCodes(codes=codes), IntToFloatTensor, PreBatchAsItem, PostBatchAsItem])<jupyter_output><empty_output><jupyter_text>Batch Transforms on CPU Example<jupyter_code>#|hide
from fastcore.basics import num_cpus

from fastai.data.external import URLs, untar_data
from fastai.data.block import DataBlock, CategoryBlock
from fastai.data.transforms import GrandparentSplitter, get_image_files, parent_label, Normalize
from fastai.vision.augment import aug_transforms
from fastai.vision.core import imagenet_stats
#|slow
with no_random():
    imagenette = untar_data(URLs.IMAGENETTE_320)

    dblock = DataBlock(blocks=(ImageCPUBlock, CategoryBlock),
                        splitter=GrandparentSplitter(valid_name='val'),
                        get_items=get_image_files, get_y=parent_label,
                        item_tfms=aug_transforms(size=128),
                        batch_tfms=Normalize.from_stats(*imagenet_stats))
    dls =  dblock.dataloaders(imagenette, bs=9, num_workers=num_cpus())

    dls.show_batch()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07887788778877888, 'fraction_numerical': 0.005280528052805281, 'mean_word_length': 4.817658349328215, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '532181', 'license': 'MIT', 'n_tokens_mistral': 958, 'n_tokens_neox': 925, 'n_words': 238, 'path': 'nbs/vision.data.ipynb', 'repo_name': 'warner-benjamin/fastxtend', 'size': '3030'}