Source code for stylish.filesystem

# :coding: utf-8

import os
import re
import unicodedata
import errno
import tempfile
import datetime

import numpy as np
import imageio
import skimage.transform

import stylish.logging


[docs]def create_log_path(style_path, relative_path=None): """Return :term:`Tensorflow` log path. Example:: >>> create_log_path("/path/to/Foo.jpg") "/tmp/stylish/log/foo-2019-09-14_15:12:11/" >>> create_log_path("/path/to/Foo.jpg", relative_path="/path") "/path/stylish/log/foo-2019-09-14_15:12:11/" :param style_path: path to an image from which the style features will be extracted. :param relative_path: Path to a folder to generate logs into. The temporary folder is used otherwise. :return: Path to save :term:`Tensorflow` logs. """ name = stylish.filesystem.sanitise_value( os.path.basename(style_path.split(".", 1)[0]), case_sensitive=False ) name += "-{}".format(datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")) root_path = relative_path or tempfile.gettempdir() path = os.path.join(root_path, "stylish", "log", name) # Attempt to create the path if necessary. ensure_directory(path) return path
[docs]def load_image(path, image_size=None): """Return 3-D Numpy array from image *path*. :param path: path to image file to load. :param image_size: targeted size of the image matrix loaded. By default, the image will not be resized. :return: 3-D Numpy array representing the image loaded. .. note:: `Lists of all formats currently supported <https://imageio.readthedocs.io/en/stable/formats.html>`_ """ logger = stylish.logging.Logger(__name__ + ".load_image") logger.debug("Load image from path: {!r}".format(path)) image = imageio.imread(path).astype(np.float) # If the image is monochrome, make it into an RGB image. if not (len(image.shape) == 3 and image.shape[2] == 3): image = np.dstack((image, image, image)) if image_size is not None: image = skimage.transform.resize(image, image_size) return image
[docs]def save_image(image, path): """Save *image_matrix* to *path*. :param image: 3-D Numpy array representing the image to save. :param path: path to image file to save *image* into. :return: None .. note:: `Lists of all formats currently supported <https://imageio.readthedocs.io/en/stable/formats.html>`_ """ image = np.clip(image, 0, 255).astype(np.uint8) imageio.imwrite(path, image)
[docs]def fetch_images(path, limit=None): """Return list of image paths from *path*. :param path: path to the directory containing all images to fetch. :param limit: maximum number of files to fetch from *path*. By default, all files are fetched. :return: list of image file path. """ if not os.path.isdir(path) or not os.access(path, os.R_OK): raise OSError("The image folder '{}' is incorrect".format(path)) images = [] for image in os.listdir(path)[:limit]: images.append(os.path.join(path, image)) return images
[docs]def ensure_directory(path): """Ensure directory exists at *path*. :param path: directory path. :return: None """ # Explicitly indicate that path should be a directory as default OSError # raised by 'os.makedirs' just indicates that the file exists, which is a # bit confusing for user. if os.path.isfile(path): raise OSError("'{}' should be a directory".format(path)) try: os.makedirs(path) except OSError as error: if error.errno != errno.EEXIST: raise if not os.path.isdir(path): raise
[docs]def sanitise_value(value, substitution_character="_", case_sensitive=True): """Return *value* suitable for use with filesystem. :param value: string value to sanitise. :param substitution_character: string character to replace awkward characters with. Default is "_". :param case_sensitive: indicate whether sanitised value should be kept with original case. Otherwise, the sanitised value will be return in lowercase. By default, the original case is preserved. :return: sanitised value. """ value = unicodedata.normalize("NFKD", value) value = re.sub(r"[^\w._\-\\/:%]", substitution_character, value) value = value.strip() if not case_sensitive: value = value.lower() return value