! [ -e /content ] && pip install -Uqq fastai # 在Colab上升级fastai
视觉工具
from __future__ import annotations
import uuid
from fastai.torch_basics import *
from fastai.data.all import *
from fastai.vision.core import *
from fastdownload import download_url
from pathlib import Path
from nbdev.showdoc import *
一些实用工具函数,用于快速下载一批图片,检查它们并进行预处理调整大小
def _get_downloaded_image_filename(dest, name, suffix):
= 1
start_index = name
candidate_name
while (dest/f"{candidate_name}{suffix}").is_file():
= f"{candidate_name}{start_index}"
candidate_name += 1
start_index
return candidate_name
def _download_image_inner(dest, inp, timeout=4, preserve_filename=False):
= inp
i,url = url.split("?")[0]
url = Path(url)
url_path = url_path.suffix if url_path.suffix else '.jpg'
suffix = _get_downloaded_image_filename(dest, url_path.stem, suffix) if preserve_filename else str(uuid.uuid4())
name try: download_url(url, dest/f"{name}{suffix}", show_progress=False, timeout=timeout)
except Exception as e: f"Couldn't download {url}."
with tempfile.TemporaryDirectory() as d:
= Path(d)
d = "https://www.fast.ai/images/jh-head.jpg"
url 125,url))
_download_image_inner(d, (len(d.ls()), 1)
test_eq(
with tempfile.TemporaryDirectory() as d:
= Path(d)
d = "https://www.fast.ai/images/jh-head.jpg"
url
125,url), preserve_filename=True)
_download_image_inner(d, (assert (d/'jh-head.jpg').is_file()
assert not (d/'jh-head.jpg1').exists()
125,url), preserve_filename=True)
_download_image_inner(d, (assert (d/'jh-head.jpg').is_file()
assert (d/'jh-head1.jpg').is_file()
def download_images(dest, url_file=None, urls=None, max_pics=1000, n_workers=8, timeout=4, preserve_filename=False):
"Download images listed in text file `url_file` to path `dest`, at most `max_pics`"
if urls is None: urls = url_file.read_text().strip().split("\n")[:max_pics]
= Path(dest)
dest =True)
dest.mkdir(exist_ok=timeout, preserve_filename=preserve_filename),
parallel(partial(_download_image_inner, dest, timeoutlist(enumerate(urls)), n_workers=n_workers, threadpool=True)
with tempfile.TemporaryDirectory() as d:
= Path(d)
d = d/'urls.txt'
url_file "\n".join([f"https://www.fast.ai/images/{n}" for n in "jh-head.jpg headshot-small.jpg".split()]))
url_file.write_text(
=True)
download_images(d, url_file, preserve_filenameassert (d/'jh-head.jpg').is_file()
assert (d/'headshot-small.jpg').is_file()
assert not (d/'jh-head1.jpg').exists()
def resize_to(img, targ_sz, use_min=False):
"Size to resize to, to hit `targ_sz` at same aspect ratio, in PIL coords (i.e w*h)"
= img.size
w,h = (min if use_min else max)(w,h)
min_sz = targ_sz/min_sz
ratio return int(w*ratio),int(h*ratio)
class _FakeImg():
def __init__(self, size): self.size=size
= _FakeImg((200,500))
img 400), [160,400])
test_eq(resize_to(img, 400, use_min=True), [400,1000]) test_eq(resize_to(img,
def verify_image(fn):
"Confirm that `fn` can be opened"
try:
= Image.open(fn)
im 32,32))
im.draft(im.mode, (
im.load()return True
except: return False
def verify_images(fns):
"Find images in `fns` that can't be opened"
return L(fns[i] for i,o in enumerate(parallel(verify_image, fns)) if not o)
def resize_image(file, dest, src='.', max_size=None, n_channels=3, ext=None,
=None, resample=BILINEAR, resume=False, **kwargs ):
img_format"Resize file to dest to max_size"
= Path(dest)
dest
= dest/file
dest_fname =True, parents=True)
dest_fname.parent.mkdir(exist_okfile = Path(src)/file
if resume and dest_fname.exists(): return
if not verify_image(file): return
= Image.open(file)
img = np.array(img)
imgarr = 1 if len(imgarr.shape) == 2 else imgarr.shape[2]
img_channels if ext is not None: dest_fname=dest_fname.with_suffix(ext)
if (max_size is not None and (img.height > max_size or img.width > max_size)) or img_channels != n_channels:
if max_size is not None:
= resize_to(img, max_size)
new_sz = img.resize(new_sz, resample=resample)
img if n_channels == 3: img = img.convert("RGB")
**kwargs)
img.save(dest_fname, img_format, elif file != dest_fname : shutil.copy2(file, dest_fname)
file = 'puppy.jpg'
= Path('.')
dest file, dest, src='images', max_size=400)
resize_image(= Image.open(dest/file)
im 1],400)
test_eq(im.shape[/file).unlink() (dest
file = 'puppy.jpg'
= Path('images')
dest file, dest, src=dest, max_size=None) resize_image(
def resize_images(path, max_workers=defaults.cpus, max_size=None, recurse=False,
=Path('.'), n_channels=3, ext=None, img_format=None, resample=BILINEAR,
dest=None, **kwargs):
resume"Resize files on path recursively to dest to max_size"
= Path(path)
path if resume is None and dest != Path('.'): resume=False
=True)
os.makedirs(dest, exist_ok= get_image_files(path, recurse=recurse)
files = [o.relative_to(path) for o in files]
files =path, n_workers=max_workers, max_size=max_size, dest=dest, n_channels=n_channels, ext=ext,
parallel(resize_image, files, src=img_format, resample=resample, resume=resume, **kwargs) img_format
with tempfile.TemporaryDirectory() as d:
= Path(d)/'resized_images'
dest 'images', max_size=100, dest=dest, max_workers=0, recurse=True) resize_images(
导出 -
from nbdev import nbdev_export
nbdev_export()