ORB Feature Matching (Rotation / Scale / Theme Robust)

Pixel template matching — match_template, match_masked — correlates the template’s pixels against the screen, so it breaks the moment the target is rotated, scaled by a factor you did not list, or re-coloured (a light-vs-dark theme, a hover state, a different skin). feature_match instead matches keypoints: distinctive corners described by orientation-invariant binary descriptors (ORB), then fits a RANSAC homography through the consistent ones. It locates the element under rotation, scale and appearance change, and reports the four projected corners plus the inlier count as a built-in confidence signal.

It runs on an injectable haystack image (ndarray / path / PIL), so it is unit-testable on synthetic arrays without a real screen. ORB, the brute-force matcher and findHomography are all in core OpenCV (no contrib modules); OpenCV + NumPy come in via je_open_cv. Imports no PySide6.

Headless API

from je_auto_control import feature_match

hit = feature_match("logo.png", min_inliers=12)
if hit:
    click(*hit.center)            # centre of the located quad
    print(hit.corners)            # 4 [x, y] points, in template order
    print(hit.inliers, hit.score) # geometric inliers and inlier fraction

feature_match returns a FeatureMatch (corners, center, inliers, matches, score) or None when fewer than min_inliers geometrically consistent matches survive. ratio is Lowe’s ratio-test cutoff (lower = stricter); max_features caps the ORB keypoint budget. The ORB border and patch sizes are scaled down automatically for icon-sized templates, which OpenCV’s defaults would otherwise reject outright.

Executor command

AC_feature_match takes template plus region / max_features / ratio / min_inliers and returns {found, match}. It is exposed as the MCP tool ac_feature_match and as a Script Builder command under Image.