BBoxMaskPose-demo / sam2 /visualization.py
Miroslav Purkrabek
add code
a249588
import os
import cv2
import numpy as np
from sam2.distinctipy import get_colors
from pycocotools import mask as Mask
def batch_visualize_masks(args, image, masks_rle, image_kpts, bboxes_xyxy, dt_bboxes, gt_masks_raw, bbox_ious, mask_ious, image_path=None, mask_out=False, alpha=1.0):
# Decode dt_masks_rle
dt_masks = []
for mask_rle in masks_rle:
mask = Mask.decode(mask_rle)
dt_masks.append(mask)
dt_masks = np.array(dt_masks)
# Decode gt_masks_raw
gt_masks = []
for gt_mask in gt_masks_raw:
if gt_mask is None:
gt_masks.append(np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8))
else:
# gt_mask_rle = Mask.frPyObjects(gt_mask, image.shape[0], image.shape[1])
# gt_mask_rle = Mask.merge(gt_mask_rle)
gt_mask_rle = gt_mask
mask = Mask.decode(gt_mask_rle)
gt_masks.append(mask)
gt_masks = np.array(gt_masks)
# Generate random color for each mask
if mask_out:
dt_mask_image = dt_masks.max(axis=0)
dt_mask_image = (~ dt_mask_image.astype(bool)).astype(np.uint8)
dt_mask_image = cv2.resize(dt_mask_image, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
dt_mask_image = image * dt_mask_image[:, :, None]
dt_mask_image = cv2.addWeighted(image, 1-alpha, dt_mask_image, alpha, 0)
else:
colors = (np.array(get_colors(dt_masks.shape[0])) * 255).astype(int)
# colors = np.random.randint(0, 255, (dt_masks.shape[0], 3))
# # Make sure no colors are too dark
# np.clip(colors, 50, 255, out=colors)
# Repeat masks to 3 channels
dt_masks = np.repeat(dt_masks[:, :, :, None], 3, axis=3)
gt_masks = np.repeat(gt_masks[:, :, :, None], 3, axis=3)
# Colorize masks
dt_masks = dt_masks * colors[:, None, None, :]
gt_masks = gt_masks * colors[:, None, None, :]
# # Remove masks that are too small
# dt_masks_area = dt_masks.any(axis=3).sum(axis=(1, 2))
# dt_masks[dt_masks_area < 300*300] = 0
# Collapse masks to 3 channels
dt_mask_image = dt_masks.max(axis=0)
gt_mask_image = gt_masks.max(axis=0)
# Convert to uint8
dt_mask_image = dt_mask_image.astype(np.uint8)
gt_mask_image = gt_mask_image.astype(np.uint8)
# Resize masks to image size
dt_mask_image = cv2.resize(dt_mask_image, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
gt_mask_image = cv2.resize(gt_mask_image, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
# Add masks to image
if not mask_out:
dt_mask_image = cv2.addWeighted(image, 0.6, dt_mask_image, 0.4, 0)
# Draw contours around the masks
for mask, color in zip(dt_masks, colors):
color = color.astype(int).tolist()
mask = mask.astype(np.uint8)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
mask = cv2.resize(mask, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(dt_mask_image, contours, -1, color, 1)
gt_mask_image = cv2.addWeighted(image, 0.6, gt_mask_image, 0.4, 0)
# Draw keypoints
if image_kpts is not None and not mask_out:
for instance_kpts, color in zip(image_kpts, colors):
color = tuple(color.astype(int).tolist())
for kpt in instance_kpts:
cv2.circle(dt_mask_image, kpt.astype(int)[:2], 3, color, -1)
cv2.circle(gt_mask_image, kpt.astype(int)[:2], 3, color, -1)
# Draw bboxes
if bboxes_xyxy is not None and not mask_out:
bboxes_xyxy = np.array(bboxes_xyxy)
dt_bboxes = np.array(dt_bboxes)
dt_bboxes[:, 2:] += dt_bboxes[:, :2]
for gt_bbox, dt_bbox, color, biou in zip(bboxes_xyxy, dt_bboxes, colors, bbox_ious):
color = tuple(color.astype(int).tolist())
gbox = gt_bbox.astype(int)
dbox = dt_bbox.astype(int)
cv2.rectangle(dt_mask_image, (dbox[0], dbox[1]), (dbox[2], dbox[3]), color, 2)
cv2.rectangle(gt_mask_image, (gbox[0], gbox[1]), (gbox[2], gbox[3]), color, 2)
# Write IOU on th etop-left corner of the bbox
# cv2.putText(dt_mask_image, "{:.2f}".format(biou), (dbox[0], dbox[1]-2), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
# cv2.putText(gt_mask_image, "{:.2f}".format(biou), (gbox[0], gbox[1]-2), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
# Save the image
bbox_ious = np.array(bbox_ious)
mask_ious = np.array(mask_ious)
if image_path is not None:
save_name = os.path.basename(image_path)
else:
save_name = "batch_bbox_{:06.2f}_mask_{:06.2f}_{:02d}kpts_{:06d}.jpg".format(
bbox_ious.mean(), mask_ious.mean(), args.num_pos_keypoints, np.random.randint(1000000),
)
if 'debug_folder' not in args:
args.debug_folder = "debug"
if mask_out:
cv2.imwrite(os.path.join(args.debug_folder, save_name), dt_mask_image)
else:
cv2.imwrite(os.path.join(args.debug_folder, save_name), np.hstack([gt_mask_image, dt_mask_image]))