Source code
This commit is contained in:
81
src/data/generator.py
Normal file
81
src/data/generator.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import numpy as np
|
||||
import cv2
|
||||
from typing import Tuple, List
|
||||
|
||||
# Image and Grid constants
|
||||
IMG_SIZE = 128
|
||||
GRID_SIZE = 16
|
||||
SPOT_RADIUS = 6 # Approximate radius in pixels
|
||||
|
||||
# Colors (BGR)
|
||||
FACE_COLOR = (180, 220, 240) # Pale cream/tan
|
||||
SPOT_COLOR = (50, 50, 200) # Reddish-orange
|
||||
EYE_COLOR = (0, 0, 0)
|
||||
|
||||
def extract_coords(pid: int, mode: str = "standard") -> List[Tuple[int, int]]:
|
||||
"""Extracts four (x, y) coordinates from a 32-bit PID/EC.
|
||||
|
||||
Standard (Little-Endian): Byte 0 (LL), 1 (LR), 2 (UL), 3 (UR)
|
||||
BDSP (Big-Endian): Byte 3 (LL), 2 (LR), 1 (UL), 0 (UR)
|
||||
"""
|
||||
bytes_list = [
|
||||
(pid >> 0) & 0xFF, # Byte 0
|
||||
(pid >> 8) & 0xFF, # Byte 1
|
||||
(pid >> 16) & 0xFF, # Byte 2
|
||||
(pid >> 24) & 0xFF, # Byte 3
|
||||
]
|
||||
|
||||
if mode == "bdsp":
|
||||
# BDSP reads the bytes in reverse order
|
||||
ordered_bytes = [bytes_list[3], bytes_list[2], bytes_list[1], bytes_list[0]]
|
||||
else:
|
||||
ordered_bytes = bytes_list
|
||||
|
||||
coords = []
|
||||
for byte in ordered_bytes:
|
||||
x = byte & 0x0F
|
||||
y = (byte >> 4) & 0x0F
|
||||
coords.append((x, y))
|
||||
return coords
|
||||
|
||||
def generate_spinda_face(pid: int, mode: str = "standard") -> np.ndarray:
|
||||
"""Generates a procedural Spinda face with spots based on the PID."""
|
||||
# Create blank canvas (white)
|
||||
img = np.ones((IMG_SIZE, IMG_SIZE, 3), dtype=np.uint8) * 255
|
||||
|
||||
# Draw Ears
|
||||
cv2.circle(img, (IMG_SIZE // 2 - 40, IMG_SIZE // 2 - 50), 20, FACE_COLOR, -1)
|
||||
cv2.circle(img, (IMG_SIZE // 2 - 40, IMG_SIZE // 2 - 50), 20, (0, 0, 0), 2)
|
||||
cv2.circle(img, (IMG_SIZE // 2 + 40, IMG_SIZE // 2 - 50), 20, FACE_COLOR, -1)
|
||||
cv2.circle(img, (IMG_SIZE // 2 + 40, IMG_SIZE // 2 - 50), 20, (0, 0, 0), 2)
|
||||
|
||||
# Draw main face (oval)
|
||||
center = (IMG_SIZE // 2, IMG_SIZE // 2)
|
||||
axes = (50, 60)
|
||||
cv2.ellipse(img, center, axes, 0, 0, 360, FACE_COLOR, -1)
|
||||
cv2.ellipse(img, center, axes, 0, 0, 360, (0, 0, 0), 2) # Outline
|
||||
|
||||
# Fixed Eyes
|
||||
cv2.circle(img, (center[0] - 15, center[1] - 10), 4, EYE_COLOR, -1)
|
||||
cv2.circle(img, (center[0] + 15, center[1] - 10), 4, EYE_COLOR, -1)
|
||||
|
||||
# Define Spot Zones (Relative to the 16x16 grid)
|
||||
# Heuristic mapping for a more "Pokemon-like" layout
|
||||
# Spot 1 (LL), Spot 2 (LR), Spot 3 (UL), Spot 4 (UR)
|
||||
# These offsets are designed to place spots in their respective quadrants
|
||||
quadrant_offsets = [
|
||||
(center[0] - 45, center[1] + 5), # LL (Face)
|
||||
(center[0] + 5, center[1] + 5), # LR (Face)
|
||||
(center[0] - 45, center[1] - 55), # UL (Ear/Upper Face)
|
||||
(center[0] + 5, center[1] - 55), # UR (Ear/Upper Face)
|
||||
]
|
||||
|
||||
coords = extract_coords(pid, mode=mode)
|
||||
for i, (x, y) in enumerate(coords):
|
||||
offset_x, offset_y = quadrant_offsets[i]
|
||||
px = int(offset_x + x * 2.5) # Scale grid to quadrant
|
||||
py = int(offset_y + y * 2.5)
|
||||
|
||||
cv2.circle(img, (px, py), SPOT_RADIUS, SPOT_COLOR, -1)
|
||||
|
||||
return img
|
||||
Reference in New Issue
Block a user