This commit is contained in:
SkalskiP committed 2023-10-18 23:10:36 +02:00
1 parent 586ff5b3fb
commit 2fed8ae0c3
1 file changed
+44 -24
+44 -24
View File
@@ -1,3 +1,4 @@
import os
from typing import Optional, Union
import cv2
@@ -171,40 +172,59 @@ def draw_text(
def draw_image(
scene: np.ndarray, image: Union[str, np.ndarray], opacity: float, rect: Rect
scene: np.ndarray,
image: Union[str, np.ndarray],
opacity: float,
rect: Rect
) -> np.ndarray:
"""
Draws an image onto a given scene with specified opacity and dimensions.
Args:
scene (np.ndarray): Background image where the new image will be drawn.
image (Union[str, np.ndarray]): Image to draw.
opacity (float): Opacity of the image to be drawn.
rect (Rect): Rectangle specifying where to draw the image.
Returns:
np.ndarray: The updated scene.
Raises:
FileNotFoundError: If the image path does not exist.
ValueError: For invalid opacity or rectangle dimensions.
"""
# Load image if a path is provided
# Validate and load image
if isinstance(image, str):
if not os.path.exists(image):
raise FileNotFoundError(f"Image path ('{image}') does not exist.")
image = cv2.imread(image, cv2.IMREAD_UNCHANGED)
# Resize the image
# Validate opacity
if not 0.0 <= opacity <= 1.0:
raise ValueError("Opacity must be between 0.0 and 1.0.")
# Validate rectangle dimensions
if rect.x < 0 or rect.y < 0 or \
rect.x + rect.width > scene.shape[1] or rect.y + rect.height > scene.shape[
0]:
raise ValueError("Invalid rectangle dimensions.")
# Resize and isolate alpha channel
image = cv2.resize(image, (rect.width, rect.height))
alpha_channel = image[:, :, 3] if image.shape[2] == 4 else np.ones(
(rect.height, rect.width), dtype=image.dtype) * 255
alpha_scaled = cv2.convertScaleAbs(alpha_channel * opacity)
# Separate the alpha channel if present
if image.shape[2] == 4:
alpha_channel = image[:, :, 3]
image = image[:, :, :3]
else:
alpha_channel = np.ones((rect.height, rect.width), dtype=np.uint8) * 255
# Perform blending
scene_roi = scene[rect.y:rect.y + rect.height, rect.x:rect.x + rect.width]
alpha_float = alpha_scaled.astype(np.float32) / 255.0
blended_roi = cv2.convertScaleAbs(
(1 - alpha_float[..., np.newaxis]) * scene_roi + alpha_float[
..., np.newaxis] * image[:, :, :3]
)
# Apply opacity to the alpha channel
alpha_channel = cv2.convertScaleAbs(alpha_channel * opacity)
# Get the ROI from the scene
scene_roi = scene[rect.y : rect.y + rect.height, rect.x : rect.x + rect.width]
# Manually apply alpha blending
alpha_float = alpha_channel.astype(np.float32) / 255.0
blended_roi = (
(1.0 - alpha_float[..., np.newaxis]) * scene_roi.astype(np.float32)
) + (alpha_float[..., np.newaxis] * image.astype(np.float32))
blended_roi = blended_roi.astype(np.uint8)
# Insert blended ROI back into the scene
scene[rect.y : rect.y + rect.height, rect.x : rect.x + rect.width] = blended_roi
# Update the scene
scene[rect.y:rect.y + rect.height, rect.x:rect.x + rect.width] = blended_roi
return scene