skills/cv/rotation-search-point-registration/SKILL.md
Brute-force a 2D rotation angle over a coarse grid to align field-coordinate points with image-plane detections when the camera angle is unknown
npx skillsauth add wenmin-wu/ds-skills cv-rotation-search-point-registrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When you have two point sets — field-coordinate positions from a tracking system and image-plane detections from a camera — but the camera angle is unknown or varies per clip, standard homography fitting overfits with few points. A simpler, more robust approach: brute-force search a rotation grid (-30° to +30° in 3° steps), rotate the field coordinates at each angle, and pick the angle that minimizes 1D-normalized L2 distance against the sorted image x-centers. With 21 grid points and ~22 players, the search costs less than a millisecond per play and beats SVD-based fits on sparse, noisy data.
import numpy as np
def rotate_arr(u, deg):
t = np.deg2rad(deg)
R = np.array([[np.cos(t), -np.sin(t)],
[np.sin(t), np.cos(t)]])
return R @ u
def norm_arr(a):
a = a - a.min()
return a / (a.max() + 1e-9)
def best_rotation(tracking_df, image_x, deg_range=30, step=3):
pts = tracking_df[['x','y']].values.T # (2, N)
best = (1e9, None, None)
a2 = norm_arr(np.sort(image_x))
for deg in range(-deg_range, deg_range + 1, step):
rot = rotate_arr(pts, deg)
rx = np.sort(rot[0])
if len(rx) == len(a2):
d = np.linalg.norm(norm_arr(rx) - a2)
else:
d = float('inf') # handle with combinatorial deletion elsewhere
if d < best[0]:
best = (d, deg, rx)
return best # (distance, angle_deg, rotated_x)
[0, 1] via min-max — this removes scale and translationdata-ai
Scaled Pinball Loss (SPL) metric for evaluating quantile forecasts, normalized by mean absolute successive differences of training data
data-ai
Walk backward through a time series and multiplicatively rescale segments when jumps exceed a fraction of the running mean to correct data collection anomalies
testing
Transform forecasting target to next/current ratio minus one so that optimizing MAE or squared error implicitly minimizes SMAPE
tools
Convert point forecasts to prediction intervals by scaling with logit-transformed quantile ratios passed through a Normal CDF