111 lines
3.7 KiB
Python
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()
|