%load_ext autoreload %autoreload 2 from fastai.gen_doc.nbdoc import * from fastai.vision import * tfms = get_transforms(max_rotate=25) len(tfms) def get_ex(): return open_image('imgs/cat_example.jpg') def plots_f(rows, cols, width, height, **kwargs): [get_ex().apply_tfms(tfms[0], **kwargs).show(ax=ax) for i,ax in enumerate(plt.subplots( rows,cols,figsize=(width,height))[1].flatten())] plots_f(2, 4, 12, 6, size=224) jekyll_note("""In fastai we follow the convention of numpy and pytorch for image dimensions: (height, width). It's different from PIL or matplolib so don't get confused.""") plots_f(2, 4, 12, 8, size=(300,200)) plots_f(2, 4, 12, 6, size=224, padding_mode='zeros') plots_f(2, 4, 12, 6, size=224, padding_mode='border') _,axs = plt.subplots(1,3,figsize=(9,3)) for rsz,ax in zip([ResizeMethod.CROP, ResizeMethod.PAD, ResizeMethod.SQUISH], axs): get_ex().apply_tfms([crop_pad()], size=224, resize_method=rsz, padding_mode='zeros').show(ax=ax, title=rsz.name.lower()) show_doc(get_transforms, arg_comments={ 'do_flip': 'if True, a random flip is applied with probability 0.5', 'flip_vert': 'requires do_flip=True. If True, the image can be flipped vertically or rotated by 90 degrees, otherwise only an horizontal flip is applied', 'max_rotate': 'if not None, a random rotation between -max\_rotate and max\_rotate degrees is applied with probability p\_affine', 'max_zoom': 'if not 1. or less, a random zoom betweem 1. and max\_zoom is applied with probability p\_affine', 'max_lighting': 'if not None, a random lightning and contrast change controlled by max\_lighting is applied with probability p\_lighting', 'max_warp': 'if not None, a random symmetric warp of magnitude between -max\_warp and maw\_warp is applied with probability p\_affine', 'p_affine': 'the probability that each affine transform and symmetric warp is applied', 'p_lighting': 'the probability that each lighting transform is applied', 'xtra_tfms': 'a list of additional transforms you would like to be applied' }) tfms = get_transforms(max_rotate=25); len(tfms) plots_f(2, 4, 12, 6, size=224) show_doc(zoom_crop, arg_comments={ 'scale': 'Decimal or range of decimals to zoom the image', 'do_rand': "If true, transform is randomized, otherwise it's a `zoom` of `scale` and a center crop", 'p': 'Probability to apply the zoom' }) tfms = zoom_crop(scale=(0.75,2), do_rand=True) plots_f(2, 4, 12, 6, size=224) show_doc(rand_resize_crop, ignore_warn=True, arg_comments={ 'size': 'Final size of the image', 'max_scale': 'Zooms the image to a random scale up to this', 'ratios': 'Range of ratios in which a new one will be randomly picked' }) tfms = [rand_resize_crop(224)] plots_f(2, 4, 12, 6, size=224) tfm = [rotate(degrees=30, p=0.5)] fig, axs = plt.subplots(1,5,figsize=(12,4)) for ax in axs: img = get_ex().apply_tfms(tfm) title = 'Done' if tfm[0].do_run else 'Not done' img.show(ax=ax, title=title) tfm = [rotate(degrees=(-30,30))] fig, axs = plt.subplots(1,5,figsize=(12,4)) for ax in axs: img = get_ex().apply_tfms(tfm) title = f"deg={tfm[0].resolved['degrees']:.1f}" img.show(ax=ax, title=title) tfm = [rotate(degrees=(-30,30), p=0.75)] fig, axs = plt.subplots(1,5,figsize=(12,4)) for ax in axs: img = get_ex().apply_tfms(tfm) title = f"Done, deg={tfm[0].resolved['degrees']:.1f}" if tfm[0].do_run else f'Not done' img.show(ax=ax, title=title) show_doc(brightness) fig, axs = plt.subplots(1,5,figsize=(12,4)) for change, ax in zip(np.linspace(0.1,0.9,5), axs): brightness(get_ex(), change).show(ax=ax, title=f'change={change:.1f}') show_doc(contrast) fig, axs = plt.subplots(1,5,figsize=(12,4)) for scale, ax in zip(np.exp(np.linspace(log(0.5),log(2),5)), axs): contrast(get_ex(), scale).show(ax=ax, title=f'scale={scale:.2f}') show_doc(crop) fig, axs = plt.subplots(1,5,figsize=(12,4)) for center, ax in zip([[0.,0.], [0.,1.],[0.5,0.5],[1.,0.], [1.,1.]], axs): crop(get_ex(), 300, *center).show(ax=ax, title=f'center=({center[0]}, {center[1]})') show_doc(crop_pad, ignore_warn=True, arg_comments={ 'x': 'Image to transform', 'size': "Size of the crop, if it's an int, the crop will be square", 'padding_mode': "How to pad the output image ('zeros', 'border' or 'reflection')", 'row_pct': 'Between 0. and 1., position of the center on the y axis (0. is top, 1. is bottom, 0.5 is center)', 'col_pct': 'Between 0. and 1., position of the center on the x axis (0. is left, 1. is right, 0.5 is center)' }) fig, axs = plt.subplots(1,5,figsize=(12,4)) for size, ax in zip(np.linspace(200,600,5), axs): crop_pad(get_ex(), int(size), 'zeros', 0.,0.).show(ax=ax, title=f'size = {int(size)}') show_doc(dihedral) fig, axs = plt.subplots(2,4,figsize=(12,8)) for k, ax in enumerate(axs.flatten()): dihedral(get_ex(), k).show(ax=ax, title=f'k={k}') plt.tight_layout() show_doc(dihedral_affine) show_doc(flip_lr) fig, axs = plt.subplots(1,2,figsize=(6,4)) get_ex().show(ax=axs[0], title=f'no flip') flip_lr(get_ex()).show(ax=axs[1], title=f'flip') show_doc(flip_affine) show_doc(jitter, doc_string=False) fig, axs = plt.subplots(1,5,figsize=(12,4)) for magnitude, ax in zip(np.linspace(-0.05,0.05,5), axs): tfm = jitter(magnitude=magnitude) get_ex().jitter(magnitude).show(ax=ax, title=f'magnitude={magnitude:.2f}') show_doc(pad) fig, axs = plt.subplots(1,3,figsize=(12,4)) for mode, ax in zip(['zeros', 'border', 'reflection'], axs): pad(get_ex(), 50, mode).show(ax=ax, title=f'mode={mode}') show_doc(perspective_warp) fig, axs = plt.subplots(2,4,figsize=(12,8)) for i, ax in enumerate(axs.flatten()): magnitudes = torch.tensor(np.zeros(8)) magnitudes[i] = 0.5 perspective_warp(get_ex(), magnitudes).show(ax=ax, title=f'coord {i}') jekyll_note("""In fastai we follow the convention of numpy and pytorch for image dimensions: (height, width). It's different from PIL or matplotlib, so don't get confused. Passing size=(300,200) for instance will give you a height of 300 and a width of 200.""") show_doc(rotate) fig, axs = plt.subplots(1,5,figsize=(12,4)) for deg, ax in zip(np.linspace(-60,60,5), axs): get_ex().rotate(degrees=deg).show(ax=ax, title=f'degrees={deg}') show_doc(rgb_randomize) fig, axs = plt.subplots(3,3,figsize=(12,12)) channels = ['Red', 'Green', 'Blue'] for i in np.arange(0, 3): for thresh, ax in zip(np.linspace(0.2, 0.99, 3), axs[:, i]): get_ex().rgb_randomize(channel = i, thresh = thresh).show( ax=ax, title = f'{channels[i]}, thresh={thresh}') show_doc(skew) fig, axs = plt.subplots(2,4,figsize=(12,8)) for i, ax in enumerate(axs.flatten()): get_ex().skew(i, 0.2).show(ax=ax, title=f'direction={i}') show_doc(squish) fig, axs = plt.subplots(1,5,figsize=(12,4)) for scale, ax in zip(np.linspace(0.66,1.33,5), axs): get_ex().squish(scale=scale).show(ax=ax, title=f'scale={scale:.2f}') show_doc(symmetric_warp) tfm = symmetric_warp(magnitude=(-0.2,0.2)) _, axs = plt.subplots(2,4,figsize=(12,6)) for ax in axs.flatten(): img = get_ex().apply_tfms(tfm, padding_mode='zeros') img.show(ax=ax) show_doc(tilt) fig, axs = plt.subplots(2,4,figsize=(12,8)) for i in range(4): get_ex().tilt(i, 0.4).show(ax=axs[0,i], title=f'direction={i}, fwd') get_ex().tilt(i, -0.4).show(ax=axs[1,i], title=f'direction={i}, bwd') show_doc(zoom) fig, axs = plt.subplots(1,5,figsize=(12,4)) for scale, ax in zip(np.linspace(1., 1.5,5), axs): get_ex().zoom(scale=scale).show(ax=ax, title=f'scale={scale:.2f}') show_doc(cutout) tfms = [cutout()] fig, axs = plt.subplots(1,5,figsize=(12,4)) for ax in axs: get_ex().apply_tfms(tfms).show(ax=ax) tfms = [cutout(n_holes=(1,4), length=(10, 160), p=.5)] fig, axs = plt.subplots(1,5,figsize=(12,4)) for ax in axs: get_ex().apply_tfms(tfms).show(ax=ax) show_doc(rand_crop) tfm = rand_crop() _, axs = plt.subplots(2,4,figsize=(12,6)) for ax in axs.flatten(): img = get_ex().apply_tfms(tfm, size=224) img.show(ax=ax) show_doc(rand_pad) tfm = rand_pad(4, 224) _, axs = plt.subplots(2,4,figsize=(12,6)) for ax in axs.flatten(): img = get_ex().apply_tfms(tfm, size=224) img.show(ax=ax) show_doc(rand_zoom) tfm = rand_zoom(scale=(1.,1.5)) _, axs = plt.subplots(2,4,figsize=(12,6)) for ax in axs.flatten(): img = get_ex().apply_tfms(tfm) img.show(ax=ax)