image utils

This commit is contained in:
Sefik Ilkin Serengil 2024-04-13 08:01:55 +01:00
parent cd36b13dde
commit b345b1dfdf
6 changed files with 59 additions and 60 deletions

View File

@ -1,9 +1,10 @@
# built-in dependencies # built-in dependencies
import os import os
import io import io
from typing import List from typing import List, Union, Tuple
import hashlib import hashlib
import base64 import base64
from pathlib import Path
# 3rd party dependencies # 3rd party dependencies
import requests import requests
@ -37,7 +38,7 @@ def list_images(path: str) -> List[str]:
return images return images
def find_hash_of_file(file_path: str) -> str: def find_image_hash(file_path: str) -> str:
""" """
Find the hash of given image file with its properties Find the hash of given image file with its properties
finding the hash of image content is costly operation finding the hash of image content is costly operation
@ -60,7 +61,50 @@ def find_hash_of_file(file_path: str) -> str:
return hasher.hexdigest() return hasher.hexdigest()
def load_base64(uri: str) -> np.ndarray: 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
"""
# The image is already a numpy array
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)}")
# The image is a base64 string
if img.startswith("data:image/"):
return load_image_from_base64(img), "base64 encoded string"
# The image is a url
if img.lower().startswith("http://") or img.lower().startswith("https://"):
return load_image_from_web(url=img), img
# The image is a path
if os.path.isfile(img) is not True:
raise ValueError(f"Confirm that {img} exists")
# image must be a file on the system then
# image name must have english characters
if img.isascii() is False:
raise ValueError(f"Input image must not have non-english characters - {img}")
img_obj_bgr = cv2.imread(img)
# img_obj_rgb = cv2.cvtColor(img_obj_bgr, cv2.COLOR_BGR2RGB)
return img_obj_bgr, img
def load_image_from_base64(uri: str) -> np.ndarray:
""" """
Load image from base64 string. Load image from base64 string.
Args: Args:

View File

@ -7,9 +7,9 @@ import cv2
from PIL import Image from PIL import Image
# project dependencies # project dependencies
from deepface.modules import preprocessing
from deepface.models.Detector import DetectedFace, FacialAreaRegion from deepface.models.Detector import DetectedFace, FacialAreaRegion
from deepface.detectors import DetectorWrapper from deepface.detectors import DetectorWrapper
from deepface.commons import image_utils
from deepface.commons import logger as log from deepface.commons import logger as log
logger = log.get_singletonish_logger() logger = log.get_singletonish_logger()
@ -63,7 +63,7 @@ def extract_faces(
resp_objs = [] resp_objs = []
# img might be path, base64 or numpy array. Convert it to numpy whatever it is. # img might be path, base64 or numpy array. Convert it to numpy whatever it is.
img, img_name = preprocessing.load_image(img_path) img, img_name = image_utils.load_image(img_path)
if img is None: if img is None:
raise ValueError(f"Exception while loading {img_name}") raise ValueError(f"Exception while loading {img_name}")

View File

@ -1,14 +1,12 @@
# built-in dependencies # built-in dependencies
import os from typing import Tuple
from typing import Union, Tuple
from pathlib import Path
# 3rd party # 3rd party
import numpy as np import numpy as np
import cv2 import cv2
# project dependencies # project dependencies
from deepface.commons import package_utils, file_utils from deepface.commons import package_utils
tf_major_version = package_utils.get_tf_major_version() tf_major_version = package_utils.get_tf_major_version()
@ -18,49 +16,6 @@ elif tf_major_version == 2:
from tensorflow.keras.preprocessing import image from tensorflow.keras.preprocessing import image
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
"""
# The image is already a numpy array
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)}")
# The image is a base64 string
if img.startswith("data:image/"):
return file_utils.load_base64(img), "base64 encoded string"
# The image is a url
if img.lower().startswith("http://") or img.lower().startswith("https://"):
return file_utils.load_image_from_web(url=img), img
# The image is a path
if os.path.isfile(img) is not True:
raise ValueError(f"Confirm that {img} exists")
# image must be a file on the system then
# image name must have english characters
if img.isascii() is False:
raise ValueError(f"Input image must not have non-english characters - {img}")
img_obj_bgr = cv2.imread(img)
# img_obj_rgb = cv2.cvtColor(img_obj_bgr, cv2.COLOR_BGR2RGB)
return img_obj_bgr, img
def normalize_input(img: np.ndarray, normalization: str = "base") -> np.ndarray: def normalize_input(img: np.ndarray, normalization: str = "base") -> np.ndarray:
"""Normalize input image. """Normalize input image.

View File

@ -10,7 +10,7 @@ import pandas as pd
from tqdm import tqdm from tqdm import tqdm
# project dependencies # project dependencies
from deepface.commons import file_utils from deepface.commons import image_utils
from deepface.modules import representation, detection, verification from deepface.modules import representation, detection, verification
from deepface.commons import logger as log from deepface.commons import logger as log
@ -143,7 +143,7 @@ def find(
pickled_images = [representation["identity"] for representation in representations] pickled_images = [representation["identity"] for representation in representations]
# Get the list of images on storage # Get the list of images on storage
storage_images = file_utils.list_images(path=db_path) storage_images = image_utils.list_images(path=db_path)
if len(storage_images) == 0: if len(storage_images) == 0:
raise ValueError(f"No item found in {db_path}") raise ValueError(f"No item found in {db_path}")
@ -160,7 +160,7 @@ def find(
if identity in old_images: if identity in old_images:
continue continue
alpha_hash = current_representation["hash"] alpha_hash = current_representation["hash"]
beta_hash = file_utils.find_hash_of_file(identity) beta_hash = image_utils.find_image_hash(identity)
if alpha_hash != beta_hash: if alpha_hash != beta_hash:
logger.debug(f"Even though {identity} represented before, it's replaced later.") logger.debug(f"Even though {identity} represented before, it's replaced later.")
replaced_images.append(identity) replaced_images.append(identity)
@ -334,7 +334,7 @@ def __find_bulk_embeddings(
desc="Finding representations", desc="Finding representations",
disable=silent, disable=silent,
): ):
file_hash = file_utils.find_hash_of_file(employee) file_hash = image_utils.find_image_hash(employee)
try: try:
img_objs = detection.extract_faces( img_objs = detection.extract_faces(

View File

@ -5,6 +5,7 @@ from typing import Any, Dict, List, Union
import numpy as np import numpy as np
# project dependencies # project dependencies
from deepface.commons import image_utils
from deepface.modules import modeling, detection, preprocessing from deepface.modules import modeling, detection, preprocessing
from deepface.models.FacialRecognition import FacialRecognition from deepface.models.FacialRecognition import FacialRecognition
@ -74,7 +75,7 @@ def represent(
) )
else: # skip else: # skip
# Try load. If load error, will raise exception internal # Try load. If load error, will raise exception internal
img, _ = preprocessing.load_image(img_path) img, _ = image_utils.load_image(img_path)
if len(img.shape) != 3: if len(img.shape) != 3:
raise ValueError(f"Input img must be 3 dimensional but it is {img.shape}") raise ValueError(f"Input img must be 3 dimensional but it is {img.shape}")

View File

@ -8,8 +8,7 @@ import pandas as pd
# project dependencies # project dependencies
from deepface import DeepFace from deepface import DeepFace
from deepface.modules import verification from deepface.modules import verification
from deepface.modules import recognition from deepface.commons import image_utils
from deepface.commons import file_utils
from deepface.commons import logger as log from deepface.commons import logger as log
logger = log.get_singletonish_logger() logger = log.get_singletonish_logger()
@ -96,7 +95,7 @@ def test_filetype_for_find():
def test_filetype_for_find_bulk_embeddings(): def test_filetype_for_find_bulk_embeddings():
imgs = file_utils.list_images("dataset") imgs = image_utils.list_images("dataset")
assert len(imgs) > 0 assert len(imgs) > 0