|
import cv2 |
|
import base64 |
|
import numpy as np |
|
from typing import Tuple |
|
|
|
def preprocess_image(image_bytes: bytes, threshold: int = 1000, scale: float = 0.5, fmt: str = "png") -> Tuple[bytes, str]: |
|
""" |
|
Preprocesses the image by checking its dimensions and downscaling it if needed. |
|
|
|
Parameters: |
|
- image_bytes: Raw image bytes. |
|
- threshold: Maximum allowed width or height (in pixels). If either dimension exceeds this, |
|
the image will be downscaled. |
|
- scale: Scale factor to use for resizing if the image is too large. |
|
- fmt: Format for re-encoding the image (e.g., "png" or "jpg"). |
|
|
|
Returns: |
|
- A tuple (new_image_bytes, new_base64_str) where: |
|
new_image_bytes: The re-encoded image bytes after potential downscaling. |
|
new_base64_str: The base64 string (without header) of the new image bytes. |
|
""" |
|
|
|
nparr = np.frombuffer(image_bytes, np.uint8) |
|
cv_image = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED) |
|
|
|
if cv_image is None: |
|
raise ValueError("Failed to decode image with OpenCV.") |
|
|
|
h, w = cv_image.shape[:2] |
|
|
|
|
|
if h > threshold or w > threshold: |
|
new_w, new_h = int(w * scale), int(h * scale) |
|
cv_image = cv2.resize(cv_image, (new_w, new_h), interpolation=cv2.INTER_AREA) |
|
|
|
ret, buf = cv2.imencode(f'.{fmt}', cv_image) |
|
|
|
if not ret: |
|
raise ValueError("Failed to re-encode image.") |
|
|
|
new_image_bytes = buf.tobytes() |
|
new_base64_str = base64.b64encode(new_image_bytes).decode("utf-8") |
|
|
|
return new_image_bytes, new_base64_str |
|
|