fastai--fastai
368 行
10 KiB
Plaintext
368 行
10 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8a01fdc1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| hide\n",
|
|
"#| eval: false\n",
|
|
"! [ -e /content ] && pip install -Uqq fastai # upgrade fastai on colab"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "raw",
|
|
"id": "493f7e72",
|
|
"metadata": {},
|
|
"source": [
|
|
"---\n",
|
|
"skip_exec: true\n",
|
|
"---"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b62b0f6e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| default_exp vision.utils"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a4ba4284",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| export\n",
|
|
"import uuid\n",
|
|
"from fastai.torch_basics import *\n",
|
|
"from fastai.data.all import *\n",
|
|
"from fastai.vision.core import *\n",
|
|
"from fastdownload import download_url\n",
|
|
"from pathlib import Path"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0c6961ab",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| hide\n",
|
|
"from nbdev.showdoc import *"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7b41b88b",
|
|
"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,
|
|
"id": "f534f4c7",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| export\n",
|
|
"def _get_downloaded_image_filename(dest, name, suffix):\n",
|
|
" start_index = 1\n",
|
|
" candidate_name = name\n",
|
|
"\n",
|
|
" while (dest/f\"{candidate_name}{suffix}\").is_file():\n",
|
|
" candidate_name = f\"{candidate_name}{start_index}\"\n",
|
|
" start_index += 1\n",
|
|
"\n",
|
|
" return candidate_name"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e94c0aa9",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| export\n",
|
|
"def _download_image_inner(dest, inp, timeout=4, preserve_filename=False):\n",
|
|
" i,url = inp\n",
|
|
" url = url.split(\"?\")[0]\n",
|
|
" url_path = Path(url)\n",
|
|
" suffix = url_path.suffix if url_path.suffix else '.jpg'\n",
|
|
" name = _get_downloaded_image_filename(dest, url_path.stem, suffix) if preserve_filename else str(uuid.uuid4())\n",
|
|
" try: download_url(url, dest/f\"{name}{suffix}\", show_progress=False, timeout=timeout)\n",
|
|
" except Exception as e: f\"Couldn't download {url}.\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d2889065",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| hide\n",
|
|
"with tempfile.TemporaryDirectory() as d:\n",
|
|
" d = Path(d)\n",
|
|
" url = \"https://www.fast.ai/images/jh-head.jpg\"\n",
|
|
" _download_image_inner(d, (125,url))\n",
|
|
" test_eq(len(d.ls()), 1)\n",
|
|
"\n",
|
|
"with tempfile.TemporaryDirectory() as d:\n",
|
|
" d = Path(d)\n",
|
|
" url = \"https://www.fast.ai/images/jh-head.jpg\"\n",
|
|
"\n",
|
|
" _download_image_inner(d, (125,url), preserve_filename=True)\n",
|
|
" assert (d/'jh-head.jpg').is_file()\n",
|
|
" assert not (d/'jh-head.jpg1').exists()\n",
|
|
"\n",
|
|
" _download_image_inner(d, (125,url), preserve_filename=True)\n",
|
|
" assert (d/'jh-head.jpg').is_file()\n",
|
|
" assert (d/'jh-head1.jpg').is_file()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d0593ffc",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| export\n",
|
|
"def download_images(dest, url_file=None, urls=None, max_pics=1000, n_workers=8, timeout=4, preserve_filename=False):\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_text().strip().split(\"\\n\")[:max_pics]\n",
|
|
" dest = Path(dest)\n",
|
|
" dest.mkdir(exist_ok=True)\n",
|
|
" parallel(partial(_download_image_inner, dest, timeout=timeout, preserve_filename=preserve_filename),\n",
|
|
" list(enumerate(urls)), n_workers=n_workers, threadpool=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4164341c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| hide\n",
|
|
"with tempfile.TemporaryDirectory() as d:\n",
|
|
" d = Path(d)\n",
|
|
" url_file = d/'urls.txt'\n",
|
|
" url_file.write_text(\"\\n\".join([f\"https://www.fast.ai/images/{n}\" for n in \"jh-head.jpg headshot-small.jpg\".split()]))\n",
|
|
" \n",
|
|
" download_images(d, url_file, preserve_filename=True)\n",
|
|
" assert (d/'jh-head.jpg').is_file()\n",
|
|
" assert (d/'headshot-small.jpg').is_file()\n",
|
|
" assert not (d/'jh-head1.jpg').exists()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "41c04937",
|
|
"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,
|
|
"id": "6a6a4d9e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class _FakeImg():\n",
|
|
" def __init__(self, size): self.size=size\n",
|
|
"\n",
|
|
"img = _FakeImg((200,500))\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,
|
|
"id": "3bff393f",
|
|
"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,
|
|
"id": "f418bded",
|
|
"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,
|
|
"id": "aad88d0a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| export\n",
|
|
"def resize_image(file, dest, src='.', max_size=None, n_channels=3, ext=None,\n",
|
|
" img_format=None, resample=BILINEAR, resume=False, **kwargs ):\n",
|
|
" \"Resize file to dest to max_size\"\n",
|
|
" dest = Path(dest)\n",
|
|
" \n",
|
|
" dest_fname = dest/file\n",
|
|
" dest_fname.parent.mkdir(exist_ok=True, parents=True)\n",
|
|
" file = Path(src)/file\n",
|
|
" if resume and dest_fname.exists(): return\n",
|
|
" if not verify_image(file): return\n",
|
|
"\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 ext is not None: dest_fname=dest_fname.with_suffix(ext)\n",
|
|
" if (max_size is not None and (img.height > max_size or img.width > max_size)) or img_channels != n_channels:\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)\n",
|
|
" elif file != dest_fname : shutil.copy2(file, dest_fname)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "027d46db",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"file = 'puppy.jpg'\n",
|
|
"dest = Path('.')\n",
|
|
"resize_image(file, dest, src='images', max_size=400)\n",
|
|
"im = Image.open(dest/file)\n",
|
|
"test_eq(im.shape[1],400)\n",
|
|
"(dest/file).unlink()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "3ec6f281",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"file = 'puppy.jpg'\n",
|
|
"dest = Path('images')\n",
|
|
"resize_image(file, dest, src=dest, max_size=None)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e9103784",
|
|
"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=BILINEAR,\n",
|
|
" resume=None, **kwargs):\n",
|
|
" \"Resize files on path recursively 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",
|
|
" files = [o.relative_to(path) for o in files]\n",
|
|
" parallel(resize_image, files, src=path, n_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,
|
|
"id": "04990b6c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"with tempfile.TemporaryDirectory() as d:\n",
|
|
" dest = Path(d)/'resized_images'\n",
|
|
" resize_images('images', max_size=100, dest=dest, max_workers=0, recurse=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d519e6ff",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Export -"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a675cf17",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#| hide\n",
|
|
"from nbdev import nbdev_export\n",
|
|
"nbdev_export()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8d585434",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"jupytext": {
|
|
"split_at_heading": true
|
|
},
|
|
"kernelspec": {
|
|
"display_name": "python3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|