saliencies / utils.py
de-Rodrigo's picture
Visualize Saliency Maps
f53adeb
import cv2
import os
import glob
import numpy as np
from datetime import datetime
def add_transparent_image(
background, foreground, alpha_factor=1.0, x_offset=None, y_offset=None
):
"""
Function sourced from StackOverflow contributor Ben.
This function was found on StackOverflow and is the work of Ben, a contributor
to the community. We are thankful for Ben's assistance by providing this useful
method.
Original Source:
https://stackoverflow.com/questions/40895785/
using-opencv-to-overlay-transparent-image-onto-another-image
"""
bg_h, bg_w, bg_channels = background.shape
fg_h, fg_w, fg_channels = foreground.shape
assert (
bg_channels == 3
), f"background image should have exactly 3 channels (RGB). found:{bg_channels}"
assert (
fg_channels == 4
), f"foreground image should have exactly 4 channels (RGBA). found:{fg_channels}"
# center by default
if x_offset is None:
x_offset = (bg_w - fg_w) // 2
if y_offset is None:
y_offset = (bg_h - fg_h) // 2
w = min(fg_w, bg_w, fg_w + x_offset, bg_w - x_offset)
h = min(fg_h, bg_h, fg_h + y_offset, bg_h - y_offset)
if w < 1 or h < 1:
return
# clip foreground and background images to the overlapping regions
bg_x = max(0, x_offset)
bg_y = max(0, y_offset)
fg_x = max(0, x_offset * -1)
fg_y = max(0, y_offset * -1)
foreground = foreground[fg_y : fg_y + h, fg_x : fg_x + w]
background_subsection = background[bg_y : bg_y + h, bg_x : bg_x + w]
# separate alpha and color channels from the foreground image
foreground_colors = foreground[:, :, :3]
foreground_colors = cv2.cvtColor(foreground_colors, cv2.COLOR_BGR2RGB)
alpha_channel = foreground[:, :, 3] / 255 * alpha_factor # 0-255 => 0.0-1.0
# construct an alpha_mask that matches the image shape
alpha_mask = np.dstack((alpha_channel, alpha_channel, alpha_channel))
# combine the background with the overlay image weighted by alpha
composite = (
background_subsection * (1 - alpha_mask) + foreground_colors * alpha_mask
)
# overwrite the section of the background image that has been updated
background[bg_y : bg_y + h, bg_x : bg_x + w] = composite
return background
def convert_tensor_to_rgba_image(tensor):
saliency_array = tensor.cpu().numpy()
# Normalize img a 0-255
if saliency_array.dtype != np.uint8:
saliency_array = (255 * saliency_array / saliency_array.max()).astype(np.uint8)
heatmap = cv2.applyColorMap(saliency_array, cv2.COLORMAP_JET)
# Pixels are transparent where no saliency [128, 0, 0] is black in COLORMAP_JET
alpha_channel = np.ones(heatmap.shape[:2], dtype=heatmap.dtype) * 255
black_pixels_mask = np.all(heatmap == [128, 0, 0], axis=-1)
alpha_channel[black_pixels_mask] = 0
# Combinar los canales RGB y alfa
saliency_rgba = cv2.merge((heatmap, alpha_channel))
return saliency_rgba
def convert_rgb_to_rgba_image(image):
alpha_channel = np.ones(image.shape[:2], dtype=image.dtype) * 255
rbga = cv2.merge((cv2.cvtColor(image, cv2.COLOR_RGB2BGR), alpha_channel))
return rbga
def label_frame(image, token):
# Add the text
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.7
text_color = (255, 255, 255)
text_thickness = 1
text_size, _ = cv2.getTextSize(token, font, font_scale, text_thickness)
text_position = (10, 10 + text_size[1])
# Draw a rectangle behind the text
rectangle_color = (0, 0, 0)
rectangle_thickness = -1
rectangle_position = (10, 10)
rectangle_size = (text_size[0] + 5, text_size[1] + 5)
cv2.rectangle(
image,
rectangle_position,
(
rectangle_position[0] + rectangle_size[0],
rectangle_position[1] + rectangle_size[1],
),
rectangle_color,
rectangle_thickness,
)
cv2.putText(
image, token, text_position, font, font_scale, text_color, text_thickness
)
return image
def saliency_video(path, sequence):
image_files = sorted(glob.glob(os.path.join(path, "*.png")), key=os.path.getctime)
image = cv2.imread(image_files[0])
height = image.shape[0]
widht = image.shape[1]
# Create a VideoWriter object to save the video
video_name = os.path.join(path, "saliency.mp4")
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
video = cv2.VideoWriter(video_name, fourcc, 5, (widht, height))
for image_file, token in zip(image_files, sequence):
image = cv2.imread(image_file)
# Write the image to the video
video.write(image)
# Release the VideoWriter object
video.release()
print(f"Video saved as {video_name}")