Draw a red rectangle highlighting the region and place a x2 zoomed inset of the region at the bottom-right corner of the image. Args: input_path: path to the input image. u, v: top-left corner of the highlight region (x=u, y=v). h, w: height and width of the hig
(
input_path: str,
u: int,
v: int,
h: int,
w: int,
out_path: str,
thickness: int = 4,
margin: int = 16,
rect_color=(0, 0, 255), # BGR: red
)
| 8 | |
| 9 | |
| 10 | def annotate_image( |
| 11 | input_path: str, |
| 12 | u: int, |
| 13 | v: int, |
| 14 | h: int, |
| 15 | w: int, |
| 16 | out_path: str, |
| 17 | thickness: int = 4, |
| 18 | margin: int = 16, |
| 19 | rect_color=(0, 0, 255), # BGR: red |
| 20 | ): |
| 21 | """ |
| 22 | Draw a red rectangle highlighting the region and place a x2 zoomed inset |
| 23 | of the region at the bottom-right corner of the image. |
| 24 | |
| 25 | Args: |
| 26 | input_path: path to the input image. |
| 27 | u, v: top-left corner of the highlight region (x=u, y=v). |
| 28 | h, w: height and width of the highlight region. |
| 29 | out_path: path to save the annotated output image. |
| 30 | thickness: rectangle line thickness in pixels. |
| 31 | margin: margin in pixels around the inset. |
| 32 | rect_color: BGR color tuple for the rectangle (default red). |
| 33 | """ |
| 34 | img = cv2.imread(input_path, cv2.IMREAD_UNCHANGED) |
| 35 | if img is None: |
| 36 | raise FileNotFoundError(f"Failed to read image: {input_path}") |
| 37 | |
| 38 | # If image has alpha channel, drop it for drawing operations. |
| 39 | if img.ndim == 3 and img.shape[2] == 4: |
| 40 | img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR) |
| 41 | |
| 42 | H, W = img.shape[:2] |
| 43 | |
| 44 | # Sanitize coordinates and clip to image bounds. |
| 45 | x1 = int(max(0, u)) |
| 46 | y1 = int(max(0, v)) |
| 47 | x2 = int(min(W, u + w)) |
| 48 | y2 = int(min(H, v + h)) |
| 49 | |
| 50 | if x2 <= x1 or y2 <= y1: |
| 51 | raise ValueError("Highlight region is empty or out of bounds after clipping.") |
| 52 | |
| 53 | # Draw highlight rectangle. |
| 54 | cv2.rectangle(img, (x1, y1), (x2, y2), rect_color, thickness=thickness) |
| 55 | |
| 56 | # Extract ROI and create x2 zoom (with fallback scaling if needed). |
| 57 | roi = img[y1:y2, x1:x2] |
| 58 | roi_h, roi_w = roi.shape[:2] |
| 59 | |
| 60 | target_w = roi_w * 2 |
| 61 | target_h = roi_h * 2 |
| 62 | |
| 63 | # Compute max allowed size for inset (respecting margins). |
| 64 | max_inset_w = max(1, W - 2 * margin) |
| 65 | max_inset_h = max(1, H - 2 * margin) |
| 66 | |
| 67 | scale = min( |