| import argparse |
| import functools |
| import logging |
| import os |
| import re |
| import string |
| import sys |
| from pathlib import Path |
| from typing import Union |
| from urllib.parse import urlparse |
|
|
| LOG = logging.getLogger(__name__) |
|
|
|
|
| class ArgumentError(ValueError): |
| """ |
| Wrapper for argument error. This exception will be raised when the arguments are invalid. |
| """ |
|
|
| pass |
|
|
|
|
| @functools.cache |
| def alphabet_id(n): |
| letters = string.ascii_uppercase |
| n_letters = len(letters) |
| if n < n_letters: |
| return letters[n] |
| _id = "" |
|
|
| while n > 0: |
| remainder = (n - 1) % n_letters |
| _id = letters[remainder] + _id |
| n = (n - 1) // n_letters |
|
|
| return _id |
|
|
|
|
| def is_url(text): |
| return urlparse(text).scheme in ["http", "https"] |
|
|
|
|
| def extract_filename_and_extension(url): |
| """ |
| Extract base filename and extension from the url. |
| :param url: URL with filename and extension, e.g., https://example.com/images/pic.jpg?param=value |
| :return: Base filename and extension, e.g., pic, jpg |
| """ |
| parsed_url = urlparse(url) |
| path = parsed_url.path |
| filename = path.split("/")[-1] |
| basename, *extension = filename.split(".") |
| return basename, f".{extension[0]}" if extension else None |
|
|
|
|
| def build_image_paths(images_paths, recursive=False): |
| filenames, urls = [], [] |
| valid_images = ["*.jpg", "*.gif", "*.png", "*.jpeg", "*.webp", "*.tif"] |
| excluded_folders = ["debug", "log"] |
| if isinstance(images_paths, str): |
| images_paths = [images_paths] |
|
|
| for filename in images_paths: |
| if is_url(filename): |
| urls.append(filename) |
| continue |
| p = Path(filename) |
| if p.is_dir(): |
| images = [p.glob(pattern) for pattern in valid_images] |
| if recursive: |
| subfolders = [f for f in p.glob("*/") if f.name not in excluded_folders] |
| images.extend( |
| [sp.rglob(pattern) for pattern in valid_images for sp in subfolders] |
| ) |
|
|
| filenames.extend(images) |
| elif p.is_file(): |
| filenames.append([p]) |
| paths = set([f.resolve() for fs in filenames for f in fs] + urls) |
| paths = list(paths) |
| if len(paths) == 0: |
| raise FileNotFoundError("No valid images in the specified path.") |
| |
| paths.sort(key=sort_file) |
| return paths |
|
|
|
|
| def sort_file(path: Union[str, Path]): |
| if isinstance(path, Path): |
| basename = path.stem |
| else: |
| basename, *_ = extract_filename_and_extension(path) |
| nums = re.findall(r"\d+", basename) |
| return (int(nums[0]) if nums else float("inf")), basename |
|
|