{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#default_exp vision.utils" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "from fastai2.torch_basics import *\n", "from fastai2.data.all import *\n", "from fastai2.vision.core import *" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#hide\n", "from nbdev.showdoc import *" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# path = untar_data(URLs.IMAGENETTE)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# path" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Vision utils\n", "\n", "> Some utils function to quickly download a bunch of images, check them and pre-resize them" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def _download_image_inner(dest, inp, timeout=4):\n", " i,url = inp\n", " suffix = re.findall(r'\\.\\w+?(?=(?:\\?|$))', url)\n", " suffix = suffix[0] if len(suffix)>0 else '.jpg'\n", " try: download_url(url, dest/f\"{i:08d}{suffix}\", overwrite=True, show_progress=False, timeout=timeout)\n", " except Exception as e: f\"Couldn't download {url}.\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with tempfile.TemporaryDirectory() as d:\n", " d = Path(d)\n", " url = \"https://www.fast.ai/images/jh-head\"\n", " _download_image_inner(d, (125,url))\n", " assert (d/'00000125.jpg').is_file()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def download_images(dest, url_file=None, urls=None, max_pics=1000, n_workers=8, timeout=4):\n", " \"Download images listed in text file `url_file` to path `dest`, at most `max_pics`\"\n", " if urls is None: urls = url_file.read().strip().split(\"\\n\")[:max_pics]\n", " dest = Path(dest)\n", " dest.mkdir(exist_ok=True)\n", " parallel(partial(_download_image_inner, dest, timeout=timeout), list(enumerate(urls)), n_workers=n_workers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "with tempfile.TemporaryDirectory() as d:\n", " d = Path(d)\n", " url_file = d/'urls.txt'\n", " url_file.write(\"\\n\".join([f\"https://www.fast.ai/images/{n}\" for n in \"jh-head thomas.JPG sg-head\".split()]))\n", " download_images(d, url_file)\n", " for i in [0,2]: assert (d/f'0000000{i}.jpg').is_file()\n", " assert (d/f'00000001.JPG').is_file()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def resize_to(img, targ_sz, use_min=False):\n", " \"Size to resize to, to hit `targ_sz` at same aspect ratio, in PIL coords (i.e w*h)\"\n", " w,h = img.size\n", " min_sz = (min if use_min else max)(w,h)\n", " ratio = targ_sz/min_sz\n", " return int(w*ratio),int(h*ratio)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class _FakeImg():\n", " def __init__(self, size): self.size=size\n", "img = _FakeImg((200,500))\n", "\n", "test_eq(resize_to(img, 400), [160,400])\n", "test_eq(resize_to(img, 400, use_min=True), [400,1000])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def verify_image(fn):\n", " \"Confirm that `fn` can be opened\"\n", " try:\n", " im = Image.open(fn)\n", " im.draft(im.mode, (32,32))\n", " im.load()\n", " return True\n", " except: return False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def verify_images(fns):\n", " \"Find images in `fns` that can't be opened\"\n", " return L(fns[i] for i,o in enumerate(parallel(verify_image, fns)) if not o)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def resize_image(file, dest, max_size=None, n_channels=3, ext=None,\n", " img_format=None, resample=Image.BILINEAR, resume=False, **kwargs ):\n", " \"Resize file to dest to max_size\"\n", " dest = Path(dest)\n", " dest_fname = dest/file.name\n", " if resume and dest_fname.exists(): return\n", " if verify_image(file):\n", " img = Image.open(file)\n", " imgarr = np.array(img)\n", " img_channels = 1 if len(imgarr.shape) == 2 else imgarr.shape[2]\n", " if (max_size is not None and (img.height > max_size or img.width > max_size)) or img_channels != n_channels:\n", " if ext is not None: dest_fname=dest_fname.with_suffix(ext)\n", " if max_size is not None:\n", " new_sz = resize_to(img, max_size)\n", " img = img.resize(new_sz, resample=resample)\n", " if n_channels == 3: img = img.convert(\"RGB\")\n", " img.save(dest_fname, img_format, **kwargs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "file = Path('images/puppy.jpg')\n", "dest = Path('.')\n", "resize_image(file, max_size=400, dest=dest)\n", "im = Image.open(dest/file.name)\n", "test_eq(im.shape[1],400)\n", "(dest/file.name).unlink()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#export\n", "def resize_images(path, max_workers=defaults.cpus, max_size=None, recurse=False,\n", " dest=Path('.'), n_channels=3, ext=None, img_format=None, resample=Image.BILINEAR,\n", " resume=None, **kwargs):\n", " \"Resize files on path recursevely to dest to max_size\"\n", " path = Path(path)\n", " if resume is None and dest != Path('.'): resume=False\n", " os.makedirs(dest, exist_ok=True)\n", " files = get_image_files(path, recurse=recurse)\n", " parallel(resize_image, files, max_workers=max_workers, max_size=max_size, dest=dest, n_channels=n_channels, ext=ext,\n", " img_format=img_format, resample=resample, resume=resume, **kwargs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "with tempfile.TemporaryDirectory() as d:\n", " dest = Path(d)/'resized_images'\n", " resize_images('images', max_size=100, dest=dest)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Export -" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Converted 00_torch_core.ipynb.\n", "Converted 01_layers.ipynb.\n", "Converted 02_data.load.ipynb.\n", "Converted 03_data.core.ipynb.\n", "Converted 04_data.external.ipynb.\n", "Converted 05_data.transforms.ipynb.\n", "Converted 06_data.block.ipynb.\n", "Converted 07_vision.core.ipynb.\n", "Converted 08_vision.data.ipynb.\n", "Converted 09_vision.augment.ipynb.\n", "Converted 09b_vision.utils.ipynb.\n", "Converted 09c_vision.widgets.ipynb.\n", "Converted 10_tutorial.pets.ipynb.\n", "Converted 11_vision.models.xresnet.ipynb.\n", "Converted 12_optimizer.ipynb.\n", "Converted 13_callback.core.ipynb.\n", "Converted 13a_learner.ipynb.\n", "Converted 13b_metrics.ipynb.\n", "Converted 14_callback.schedule.ipynb.\n", "Converted 14a_callback.data.ipynb.\n", "Converted 15_callback.hook.ipynb.\n", "Converted 15a_vision.models.unet.ipynb.\n", "Converted 16_callback.progress.ipynb.\n", "Converted 17_callback.tracker.ipynb.\n", "Converted 18_callback.fp16.ipynb.\n", "Converted 18a_callback.training.ipynb.\n", "Converted 19_callback.mixup.ipynb.\n", "Converted 20_interpret.ipynb.\n", "Converted 20a_distributed.ipynb.\n", "Converted 21_vision.learner.ipynb.\n", "Converted 22_tutorial.imagenette.ipynb.\n", "Converted 23_tutorial.vision.ipynb.\n", "Converted 24_tutorial.siamese.ipynb.\n", "Converted 24_vision.gan.ipynb.\n", "Converted 30_text.core.ipynb.\n", "Converted 31_text.data.ipynb.\n", "Converted 32_text.models.awdlstm.ipynb.\n", "Converted 33_text.models.core.ipynb.\n", "Converted 34_callback.rnn.ipynb.\n", "Converted 35_tutorial.wikitext.ipynb.\n", "Converted 36_text.models.qrnn.ipynb.\n", "Converted 37_text.learner.ipynb.\n", "Converted 38_tutorial.text.ipynb.\n", "Converted 40_tabular.core.ipynb.\n", "Converted 41_tabular.data.ipynb.\n", "Converted 42_tabular.model.ipynb.\n", "Converted 43_tabular.learner.ipynb.\n", "Converted 44_tutorial.tabular.ipynb.\n", "Converted 45_collab.ipynb.\n", "Converted 46_tutorial.collab.ipynb.\n", "Converted 50_tutorial.datablock.ipynb.\n", "Converted 60_medical.imaging.ipynb.\n", "Converted 61_tutorial.medical_imaging.ipynb.\n", "Converted 65_medical.text.ipynb.\n", "Converted 70_callback.wandb.ipynb.\n", "Converted 71_callback.tensorboard.ipynb.\n", "Converted 72_callback.neptune.ipynb.\n", "Converted 73_callback.captum.ipynb.\n", "Converted 74_callback.cutmix.ipynb.\n", "Converted 97_test_utils.ipynb.\n", "Converted 99_pytorch_doc.ipynb.\n", "Converted index.ipynb.\n", "Converted tutorial.ipynb.\n" ] } ], "source": [ "#hide\n", "from nbdev.export import notebook2script\n", "notebook2script()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "jupytext": { "split_at_heading": true }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 4 }