diff --git a/argv/run/argument.py b/argv/run/argument.py index 0d1e2a0..cb3dbb5 100644 --- a/argv/run/argument.py +++ b/argv/run/argument.py @@ -75,7 +75,7 @@ def arg_input(parser): parser.add_argument( "-i", "--input", - help="Path of the photo or directory to transform .", + help="Path or http(s) url of the photo. Or path of the directory to transform .", ) diff --git a/argv/run/config.py b/argv/run/config.py index df96ac2..b3a5655 100644 --- a/argv/run/config.py +++ b/argv/run/config.py @@ -2,7 +2,10 @@ import os import gpu_info from argv.checkpoints import set_arg_checkpoints, check_arg_checkpoints -from utils import check_image_file_validity, is_a_supported_image_file_extension +from utils import check_image_file_validity, is_a_supported_image_file_extension, check_url +from loader import Loader +from loader.fs import FSLoader +from loader.http import HTTPLoader def set_args_run_parser(args): @@ -38,12 +41,20 @@ def set_gpu_ids(args): def check_arg_input(parser, args): if not args.input: parser.error("-i, --input INPUT is required.") - if not os.path.isdir(args.input) and not os.path.isfile(args.input): - parser.error("Input {} file or directory doesn't exist.".format(args.input)) - elif os.path.isfile(args.input) and not is_a_supported_image_file_extension(args.input): - parser.error("Input {} file not supported format.".format(args.input)) - if os.path.isfile(args.input): - check_image_file_validity(args.input) + + loader = Loader.get_loader(args.input) + if loader == FSLoader: + if os.path.isfile(args.input) and not is_a_supported_image_file_extension(args.input): + parser.error("Input {} file not supported format.".format(args.input)) + if os.path.isfile(args.input): + check_image_file_validity(args.input) + elif loader == HTTPLoader: + if not check_url(args.input): + parser.error("Url {} of the http ressource doesn't exist or is not accesible.".format(args.input)) + if not is_a_supported_image_file_extension(args.input): + parser.error("Url {} is not file with a supported extension format.".format(args.input)) + else: + parser.error("Input {} is not a valid file or directory or url.".format(args.input)) return args.input diff --git a/loader/__init__.py b/loader/__init__.py new file mode 100644 index 0000000..b4bd7c0 --- /dev/null +++ b/loader/__init__.py @@ -0,0 +1,30 @@ +"""Loader.""" + + +class Loader: + """ Abstract Loader Class """ + + @staticmethod + def load(uri): + """ + Load the uri ressource + :return: image + """ + pass + + @staticmethod + def uri_validator(uri): + """ + Validate the uri for the loader + :return: True is a valid uri + """ + return False + + @staticmethod + def get_loader(uri): + from loader.fs import FSLoader + from loader.http import HTTPLoader + for loader in (FSLoader, HTTPLoader): + if loader.uri_validator(uri): + return loader + return None diff --git a/loader/fs.py b/loader/fs.py new file mode 100644 index 0000000..25c1b8d --- /dev/null +++ b/loader/fs.py @@ -0,0 +1,24 @@ +""" File Sytem Loading """ +import os + +from loader import Loader +from utils import read_image + + +class FSLoader(Loader): + """ File System Loader Class """ + @staticmethod + def load(uri): + """ + Load the file system ressource + :return: image + """ + return read_image(uri) + + @staticmethod + def uri_validator(uri): + """ + Validate the uri is a filesystem file + :return: True is a valid uri + """ + return os.path.exists(uri) diff --git a/loader/http.py b/loader/http.py new file mode 100644 index 0000000..389124b --- /dev/null +++ b/loader/http.py @@ -0,0 +1,34 @@ +import os +import re +import tempfile + +from utils import dl_file, read_image +from loader import Loader + + +regex_url = re.compile( + r'^(?:http)s?://' # http:// or https:// + r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... + r'localhost|' # localhost... + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip + r'(?::\d+)?' # optional port + r'(?:/?|[/?]\S+)$', re.IGNORECASE) + + +class HTTPLoader(Loader): + """ Abstract Loader Class """ + @staticmethod + def run(uri): + """ + Run the loader ressource + :return: image + """ + _, tmp_path = tempfile.mkstemp() + dl_file(uri, tmp_path) + img = read_image(tmp_path) + os.remove(tmp_path) + return img + + @staticmethod + def uri_validator(uri): + return regex_url.match(uri) diff --git a/processing/__init__.py b/processing/__init__.py index e7d815f..33def64 100644 --- a/processing/__init__.py +++ b/processing/__init__.py @@ -7,9 +7,10 @@ from utils import camel_case_to_str, cv2_supported_extension class Processing: + """ Abstract Processing Class """ def __init__(self, args=None): """ - Image Transformation Class Constructor. + Image Processing Class Constructor. :param input_index: index where to take the inputs (default is (-1) for previous transformation) :param args: args parameter to run the image transformation (default use Conf.args) diff --git a/processing/image.py b/processing/image.py index 3c29a49..9a8d2fd 100644 --- a/processing/image.py +++ b/processing/image.py @@ -5,7 +5,8 @@ import sys from config import Config as Conf from processing import Processing from processing.utils import select_phases -from utils import read_image, camel_case_to_str, write_image +from utils import camel_case_to_str, write_image +from loader import Loader class ImageProcessing(Processing): @@ -43,7 +44,9 @@ class ImageProcessing(Processing): def _setup(self, *args): try: - self.__image_steps = [read_image(x) if isinstance(x, str) else x for x in self.__image_steps] + self.__image_steps = [ + (Loader.get_loader(x)).run(x) if isinstance(x, str) else x for x in self.__image_steps + ] except FileNotFoundError as e: Conf.log.error(e) Conf.log.error("{} is not able to resume because it not able to load required images. " diff --git a/sample_input.png b/sample_input.png deleted file mode 100644 index 90cb59b..0000000 Binary files a/sample_input.png and /dev/null differ diff --git a/transform/gan/mask.py b/transform/gan/mask.py index cf48050..0562e1c 100644 --- a/transform/gan/mask.py +++ b/transform/gan/mask.py @@ -56,4 +56,3 @@ class MaskfinToNude(MaskImageTransformGAN): :param args: args parameter to run the image transformation (default use Conf.args) """ super().__init__("maskfin_to_nude", input_index=input_index, args=args) - diff --git a/transform/opencv/mask.py b/transform/opencv/mask.py index a7ee9c3..d9c245c 100644 --- a/transform/opencv/mask.py +++ b/transform/opencv/mask.py @@ -155,7 +155,7 @@ class MaskdetToMaskfin(MaskImageTransformOpenCV): hairmin = to_int(self.__hair_size, a_min) self.__draw_ellipse(a_max, a_min, angle, aurmax, aurmin, details, hairmax, hairmin, nipmax, nipmin, obj, - titmax, titmin, vagmax, vagmin, x, y) + titmax, titmin, vagmax, vagmin, x, y) @staticmethod def __draw_ellipse(a_max, a_min, angle, aurmax, aurmin, details, hairmax, hairmin, nipmax, nipmin, obj, diff --git a/utils.py b/utils.py index 0be4632..f53ca72 100644 --- a/utils.py +++ b/utils.py @@ -223,3 +223,12 @@ def is_a_supported_image_file_extension(path): :return: True if the extension is supported """ return os.path.splitext(path)[1] in cv2_supported_extension() + [".gif"] + + +def check_url(url): + """ + Check if a url exists withtout downloading it + :return: True if return url exists + """ + resp = requests.head(url) + return resp.status_code < 400