FaceSWAP / utils /color_utils.py
aditya-rAj19's picture
Initial commit: DeepFace Studio - AI face swap web application
e7a5a81
Raw
History Blame Contribute Delete
2.32 kB
import cv2
import numpy as np
def bgr_to_lab(image: np.ndarray) -> np.ndarray:
"""Convert BGR uint8 to float32 CIE LAB (L: 0-100, a/b: -128..127)."""
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB).astype(np.float32)
lab[:, :, 0] *= 100.0 / 255.0
lab[:, :, 1:] -= 128.0
return lab
def lab_to_bgr(lab: np.ndarray) -> np.ndarray:
"""Convert float32 CIE LAB back to BGR uint8."""
lab_cv = lab.copy()
lab_cv[:, :, 0] = lab_cv[:, :, 0] * 255.0 / 100.0
lab_cv[:, :, 1:] += 128.0
return cv2.cvtColor(np.clip(lab_cv, 0, 255).astype(np.uint8), cv2.COLOR_LAB2BGR)
def bgr_to_hsv(image: np.ndarray) -> np.ndarray:
"""Convert BGR uint8 to float32 HSV (H: 0-360, S/V: 0-100)."""
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV).astype(np.float32)
hsv[:, :, 0] *= 2.0 # OpenCV H: 0-180 -> 0-360
hsv[:, :, 1:] /= 255.0 * 100 # S,V to percent
return hsv
def hsv_to_bgr(hsv: np.ndarray) -> np.ndarray:
"""Convert float32 HSV (H:0-360, S/V:0-100) back to BGR uint8."""
hsv_cv = hsv.copy()
hsv_cv[:, :, 0] /= 2.0
hsv_cv[:, :, 1:] *= 255.0 / 100.0
return cv2.cvtColor(np.clip(hsv_cv, 0, 255).astype(np.uint8), cv2.COLOR_HSV2BGR)
def histogram_match(source: np.ndarray, reference: np.ndarray) -> np.ndarray:
"""
Match the histogram of source image to reference image.
Operates channel-by-channel on BGR images.
"""
matched = np.empty_like(source)
for ch in range(source.shape[2]):
src_ch = source[:, :, ch].ravel()
ref_ch = reference[:, :, ch].ravel()
src_hist, _ = np.histogram(src_ch, 256, [0, 256])
ref_hist, _ = np.histogram(ref_ch, 256, [0, 256])
src_cdf = np.cumsum(src_hist).astype(np.float64)
ref_cdf = np.cumsum(ref_hist).astype(np.float64)
src_cdf /= src_cdf[-1]
ref_cdf /= ref_cdf[-1]
lut = np.interp(src_cdf, ref_cdf, np.arange(256))
matched[:, :, ch] = lut[source[:, :, ch]]
return matched.astype(np.uint8)
def compute_mean_lab(image: np.ndarray, mask: np.ndarray | None = None) -> tuple:
"""Return mean L*, a*, b* for an image (optionally masked)."""
lab = bgr_to_lab(image)
if mask is not None:
region = lab[mask > 0]
else:
region = lab.reshape(-1, 3)
return tuple(region.mean(axis=0))