Files
DirtyLeague_Bot/inspect_battle_cards.py

111 lines
3.7 KiB
Python

"""
Inspection script to calibrate exact bounding boxes for:
- 5 Player cards (left vertical column)
- 5 Opponent cards (right vertical column)
on the DirtyLeague Battle Screen (3840x2050 design resolution).
"""
import os
import cv2
import numpy as np
from card_embedder import CardEmbedder
# Normalized relative coordinates (rx1, ry1, rx2, ry2) for 3840x2050
# Calibrated from actual 4K battle screenshot
PLAYER_CARD_SLOTS = [
# Slot 1 (top left)
(0.226, 0.150, 0.294, 0.278),
# Slot 2
(0.226, 0.295, 0.294, 0.423),
# Slot 3
(0.226, 0.440, 0.294, 0.568),
# Slot 4
(0.226, 0.585, 0.294, 0.713),
# Slot 5 (bottom left)
(0.226, 0.730, 0.294, 0.858),
]
OPPONENT_CARD_SLOTS = [
# Slot 1 (top right)
(0.693, 0.150, 0.761, 0.278),
# Slot 2
(0.693, 0.295, 0.761, 0.423),
# Slot 3
(0.693, 0.440, 0.761, 0.568),
# Slot 4
(0.693, 0.585, 0.761, 0.713),
# Slot 5 (bottom right)
(0.693, 0.730, 0.761, 0.858),
]
def extract_cards(frame: np.ndarray):
fh, fw = frame.shape[:2]
player_crops = []
opponent_crops = []
for rx1, ry1, rx2, ry2 in PLAYER_CARD_SLOTS:
x1, y1 = int(rx1 * fw), int(ry1 * fh)
x2, y2 = int(rx2 * fw), int(ry2 * fh)
player_crops.append(frame[y1:y2, x1:x2])
for rx1, ry1, rx2, ry2 in OPPONENT_CARD_SLOTS:
x1, y1 = int(rx1 * fw), int(ry1 * fh)
x2, y2 = int(rx2 * fw), int(ry2 * fh)
opponent_crops.append(frame[y1:y2, x1:x2])
return player_crops, opponent_crops
def main():
img_path = os.path.join("dataset", "raw", "dl_screen_20260910_233743_310.png")
if not os.path.exists(img_path):
print(f"[ERROR] Sample battle screenshot not found at: {img_path}")
return
frame = cv2.imread(img_path)
fh, fw = frame.shape[:2]
print(f"\nAnalyzing battle frame resolution: {fw}x{fh}")
player_crops, opponent_crops = extract_cards(frame)
os.makedirs("debug_cards", exist_ok=True)
embedder = CardEmbedder()
print("\n--- Player Cards (Left Column 1..5) ---")
for i, crop in enumerate(player_crops, 1):
crop_path = os.path.join("debug_cards", f"player_card_{i}.png")
cv2.imwrite(crop_path, crop)
vec = embedder.embed(crop)
print(f" Player Slot #{i}: {crop.shape[1]}x{crop.shape[0]}px | Vector norm: {np.linalg.norm(vec):.4f} | Saved to: {crop_path}")
print("\n--- Opponent Cards (Right Column 1..5) ---")
for i, crop in enumerate(opponent_crops, 1):
crop_path = os.path.join("debug_cards", f"opponent_card_{i}.png")
cv2.imwrite(crop_path, crop)
vec = embedder.embed(crop)
print(f" Opponent Slot #{i}: {crop.shape[1]}x{crop.shape[0]}px | Vector norm: {np.linalg.norm(vec):.4f} | Saved to: {crop_path}")
# Draw visual overlay on whole frame
annotated = frame.copy()
for i, (rx1, ry1, rx2, ry2) in enumerate(PLAYER_CARD_SLOTS, 1):
x1, y1 = int(rx1 * fw), int(ry1 * fh)
x2, y2 = int(rx2 * fw), int(ry2 * fh)
cv2.rectangle(annotated, (x1, y1), (x2, y2), (0, 255, 0), 3)
cv2.putText(annotated, f"Player #{i}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2)
for i, (rx1, ry1, rx2, ry2) in enumerate(OPPONENT_CARD_SLOTS, 1):
x1, y1 = int(rx1 * fw), int(ry1 * fh)
x2, y2 = int(rx2 * fw), int(ry2 * fh)
cv2.rectangle(annotated, (x1, y1), (x2, y2), (0, 0, 255), 3)
cv2.putText(annotated, f"Enemy #{i}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2)
preview_path = os.path.join("debug_cards", "annotated_battle_slots.png")
cv2.imwrite(preview_path, cv2.resize(annotated, (1920, 1025)))
print(f"\n[SUCCESS] Full annotated battle preview saved to: {preview_path}")
if __name__ == "__main__":
main()