94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
import cv2
|
|
import json
|
|
import os
|
|
import argparse
|
|
|
|
def draw_boxes_from_json(image_path: str, json_path: str, output_path: str):
|
|
# 1. Load the image
|
|
image_bgr = cv2.imread(image_path)
|
|
if image_bgr is None:
|
|
print(f"❌ Error: Cannot load image at {image_path}")
|
|
return
|
|
|
|
ih, iw = image_bgr.shape[:2]
|
|
|
|
# 2. Load the JSON data
|
|
if not os.path.exists(json_path):
|
|
print(f"❌ Error: JSON file not found at {json_path}")
|
|
return
|
|
|
|
with open(json_path, 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
|
|
# Color map for different region types (BGR format)
|
|
COLOR_MAP = {
|
|
"dialogue": (0, 200, 0), # Green
|
|
"narration": (0, 165, 255), # Orange
|
|
"reaction": (255, 200, 0), # Cyan/Blue
|
|
"sfx": (0, 0, 220), # Red
|
|
"unknown": (120, 120, 120), # Gray
|
|
}
|
|
|
|
# 3. Iterate through the JSON and draw boxes
|
|
# Sort by order to keep numbering consistent
|
|
sorted_items = sorted(data.values(), key=lambda x: x.get("order", 0))
|
|
|
|
for item in sorted_items:
|
|
bid = item.get("order", "?")
|
|
rtype = item.get("region_type", "unknown")
|
|
box = item.get("box", {})
|
|
text = item.get("corrected_ocr", "")
|
|
|
|
if not box:
|
|
continue
|
|
|
|
# Extract xywh and convert to xyxy
|
|
x1, y1 = int(box.get("x", 0)), int(box.get("y", 0))
|
|
w, h = int(box.get("w", 0)), int(box.get("h", 0))
|
|
x2, y2 = x1 + w, y1 + h
|
|
|
|
color = COLOR_MAP.get(rtype, (120, 120, 120))
|
|
|
|
# Draw the main bounding box
|
|
cv2.rectangle(image_bgr, (x1, y1), (x2, y2), color, 2)
|
|
|
|
# Prepare labels
|
|
label = f"BOX#{bid} [{rtype}]"
|
|
preview = (text[:40] + "...") if len(text) > 40 else text
|
|
|
|
font = cv2.FONT_HERSHEY_SIMPLEX
|
|
font_scale = 0.38
|
|
thickness = 1
|
|
|
|
# Draw Label Background
|
|
(lw, lh), _ = cv2.getTextSize(label, font, font_scale, thickness)
|
|
cv2.rectangle(image_bgr,
|
|
(x1, max(0, y1 - lh - 6)),
|
|
(x1 + lw + 4, y1),
|
|
color, -1)
|
|
|
|
# Draw Label Text (Box ID + Type)
|
|
cv2.putText(image_bgr, label,
|
|
(x1 + 2, max(lh, y1 - 3)),
|
|
font, font_scale, (255, 255, 255), thickness,
|
|
cv2.LINE_AA)
|
|
|
|
# Draw Preview Text below the box
|
|
cv2.putText(image_bgr, preview,
|
|
(x1 + 2, min(ih - 5, y2 + 12)),
|
|
font, font_scale * 0.85, color, thickness,
|
|
cv2.LINE_AA)
|
|
|
|
# 4. Save the final image
|
|
cv2.imwrite(output_path, image_bgr)
|
|
print(f"✅ Debug image successfully saved to: {output_path}")
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Draw bounding boxes from bubbles.json onto an image.")
|
|
parser.add_argument("image", help="Path to the original manga page image")
|
|
parser.add_argument("json", help="Path to the bubbles.json file")
|
|
parser.add_argument("--output", "-o", default="debug_clusters_from_json.png", help="Output image path")
|
|
|
|
args = parser.parse_args()
|
|
|
|
draw_boxes_from_json(args.image, args.json, args.output) |