|
|
|
|
|
import os |
|
|
import io |
|
|
from typing import List, Union, Tuple |
|
|
import hashlib |
|
|
import base64 |
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
import requests |
|
|
import numpy as np |
|
|
import cv2 |
|
|
from PIL import Image |
|
|
|
|
|
|
|
|
def list_images(path: str) -> List[str]: |
|
|
""" |
|
|
List images in a given path |
|
|
Args: |
|
|
path (str): path's location |
|
|
Returns: |
|
|
images (list): list of exact image paths |
|
|
""" |
|
|
images = [] |
|
|
for r, _, f in os.walk(path): |
|
|
for file in f: |
|
|
exact_path = os.path.join(r, file) |
|
|
|
|
|
_, ext = os.path.splitext(exact_path) |
|
|
ext_lower = ext.lower() |
|
|
|
|
|
if ext_lower not in {".jpg", ".jpeg", ".png"}: |
|
|
continue |
|
|
|
|
|
with Image.open(exact_path) as img: |
|
|
if img.format.lower() in ["jpeg", "png"]: |
|
|
images.append(exact_path) |
|
|
return images |
|
|
|
|
|
|
|
|
def find_image_hash(file_path: str) -> str: |
|
|
""" |
|
|
Find the hash of given image file with its properties |
|
|
finding the hash of image content is costly operation |
|
|
Args: |
|
|
file_path (str): exact image path |
|
|
Returns: |
|
|
hash (str): digest with sha1 algorithm |
|
|
""" |
|
|
file_stats = os.stat(file_path) |
|
|
|
|
|
|
|
|
file_size = file_stats.st_size |
|
|
creation_time = file_stats.st_ctime |
|
|
modification_time = file_stats.st_mtime |
|
|
|
|
|
properties = f"{file_size}-{creation_time}-{modification_time}" |
|
|
|
|
|
hasher = hashlib.sha1() |
|
|
hasher.update(properties.encode("utf-8")) |
|
|
return hasher.hexdigest() |
|
|
|
|
|
|
|
|
def load_image(img: Union[str, np.ndarray]) -> Tuple[np.ndarray, str]: |
|
|
""" |
|
|
Load image from path, url, base64 or numpy array. |
|
|
Args: |
|
|
img: a path, url, base64 or numpy array. |
|
|
Returns: |
|
|
image (numpy array): the loaded image in BGR format |
|
|
image name (str): image name itself |
|
|
""" |
|
|
|
|
|
|
|
|
if isinstance(img, np.ndarray): |
|
|
return img, "numpy array" |
|
|
|
|
|
if isinstance(img, Path): |
|
|
img = str(img) |
|
|
|
|
|
if not isinstance(img, str): |
|
|
raise ValueError(f"img must be numpy array or str but it is {type(img)}") |
|
|
|
|
|
|
|
|
if img.startswith("data:image/"): |
|
|
return load_image_from_base64(img), "base64 encoded string" |
|
|
|
|
|
|
|
|
if img.lower().startswith("http://") or img.lower().startswith("https://"): |
|
|
return load_image_from_web(url=img), img |
|
|
|
|
|
|
|
|
if os.path.isfile(img) is not True: |
|
|
raise ValueError(f"Confirm that {img} exists") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if img.isascii() is False: |
|
|
raise ValueError(f"Input image must not have non-english characters - {img}") |
|
|
|
|
|
img_obj_bgr = cv2.imread(img) |
|
|
|
|
|
return img_obj_bgr, img |
|
|
|
|
|
|
|
|
def load_image_from_base64(uri: str) -> np.ndarray: |
|
|
""" |
|
|
Load image from base64 string. |
|
|
Args: |
|
|
uri: a base64 string. |
|
|
Returns: |
|
|
numpy array: the loaded image. |
|
|
""" |
|
|
|
|
|
encoded_data_parts = uri.split(",") |
|
|
|
|
|
if len(encoded_data_parts) < 2: |
|
|
raise ValueError("format error in base64 encoded string") |
|
|
|
|
|
encoded_data = encoded_data_parts[1] |
|
|
decoded_bytes = base64.b64decode(encoded_data) |
|
|
|
|
|
|
|
|
|
|
|
with Image.open(io.BytesIO(decoded_bytes)) as img: |
|
|
file_type = img.format.lower() |
|
|
if file_type not in ["jpeg", "png"]: |
|
|
raise ValueError(f"input image can be jpg or png, but it is {file_type}") |
|
|
|
|
|
nparr = np.fromstring(decoded_bytes, np.uint8) |
|
|
img_bgr = cv2.imdecode(nparr, cv2.IMREAD_COLOR) |
|
|
|
|
|
return img_bgr |
|
|
|
|
|
|
|
|
def load_image_from_web(url: str) -> np.ndarray: |
|
|
""" |
|
|
Loading an image from web |
|
|
Args: |
|
|
url: link for the image |
|
|
Returns: |
|
|
img (np.ndarray): equivalent to pre-loaded image from opencv (BGR format) |
|
|
""" |
|
|
response = requests.get(url, stream=True, timeout=60) |
|
|
response.raise_for_status() |
|
|
image_array = np.asarray(bytearray(response.raw.read()), dtype=np.uint8) |
|
|
img = cv2.imdecode(image_array, cv2.IMREAD_COLOR) |
|
|
return img |
|
|
|