frame_align — ASTROSTACK align op

• 数据种类:image2d × image2d → matrix

• 调用: import fullseye as fs; fs.ledger.frame_align(reference, frame, model='similarity', threshold_sigma=5.0, max_stars=60, tolerance_px=2.0, max_shift_px=None, ransac_iters=500, seed=0, min_inliers=3)(要直接调用实现,import astrostack; astrostack.frame_align(reference, frame, model='similarity', threshold_sigma=5.0, max_stars=60, tolerance_px=2.0, max_shift_px=None, ransac_iters=500, seed=0, min_inliers=3);从台账取用则 opsastrostack.get("frame_align"))

• 经台账调用的返回值: fullseye.ledger.frame_align(...) 只返回声明的 out 类型 matrix 的值(底层函数还会返回辅助信息)。需要被丢弃的部分时,使用 fullseye.ledger.frame_align.raw(...),或直接调用 astrostack.frame_align。

• 底层返回: (matrix, info) -> matrix

用法

由恒星对应估计 frame → reference 的 2-D 变换。

流程分 3 步,各步估计的主体都是现有 op:

1. 用 star_detect 取出两幅图中的星。

2. 用偏移投票求出粗略平移(_vote_translation)。

这里不用 features.match_keypoints 是基于实测的判断:

星场的 9x9 小块彼此几乎形状相同,因此 Lowe 的比值检验

(默认 ratio=0.8)几乎会全部舍弃。128x128 中 40 颗星、真实偏移为

(+0.590, -0.540) px 的帧对上的实测:match_keypoints

返回的对应为 4 个,其中距真值 1 px 以内的为 0 个(= 可用的

1 个也没有)。同一对上投票法为 26 票 → 26 对应 → 26 内点,估计误差

0.0155 px。星场不是“没有特征”,而是“特征全都一样”,因此

正确做法是用排布的几何而非描述子。

3. 用粗略移动建立最近邻对应,

用 mosaic.proj_match_points_ransac 剔除误对应,

用 fit_transform.vector_to_similarity(依 model 而定为

vector_to_rigid / vector_to_hom_mat2d)拟合。

这里既没有写 RANSAC 循环也没有写 Umeyama。

★不能用于重复结构(2026-09-08,由 poc_print_registration 发现)。inlier_ratio 是“赞成同一答案的对应所占比例”,而不是“答案正确的概率”。在网点、织物、网格这类同一形状周期性排列的图像中,偏移一个格向量的对应关系也会获得全员赞成,因此赞成率保持 1.00,只有答案偏移了 1 个格周期(甚至好几个)。

实测:256x256、相当于 133 lpi、15 度的网点,仅偏移 (0.00, +1.30) px 的图像对,返回 inlier_ratio 1.00 / rms_px 0.78,而估计却是 (+54.24, +30.12) px。星场(128x128、40 颗星、真值(+0.59, -0.54))上 inlier_ratio 同为 1.00,估计正确。仅凭赞成率无法区分这 2 者。

能区分它们的是 vote_margin —— 投票第 2 高峰的高度除以第 1 高峰的值,0 表示只有 1 个峰,越接近 1 越表示“还有同样可信的其他答案”。同样 2 个例子中 网点 0.857 / 星场 0.143。在可能传入周期结构的路径上,请看它而不是 inlier_ratio。

若只需要平移本身,看 piv_cross_correlate 的相关面更直接,那里可以自己数出有几个峰。

*model* "translation" 只用对应差的中位数(即使只有 1 颗星也能工作)。"rigid" = 旋转 + 平移,"similarity" = + 各向同性缩放,"affine" = 6 自由度。只要视场不宽,"similarity" 就够了 (赤道仪的跟踪误差是旋转与平移,大气折射以一阶形式进入缩放)。

Returns (matrix, info):

• matrix —— (3, 3) float64。从左乘 (row, col, 1) 得到 reference 的坐标(与 fit_transform 相同的约定)。

• info —— dict。n_stars_ref / n_stars_src / n_pairs / n_inliers / inlier_ratio / shift_row / shift_col / rotation_deg / scale / rms_px(内点的残差 RMS)/ model。

fail-closed:内点少于 *min_inliers* 时抛出 ValueError。不默默返回恒等变换 —— 把配准失败的帧当作“偏移 0”混入合成,会在既无异常也无警告的情况下产生双像。

Raises ValueError:非 2-D / 形状不同 / *model* 不在 ALIGN_MODELS 中 / 任一幅图中 1 颗星也找不到 / 无法建立对应 / 内点不足时。

参考(示例数据、文献)

• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 URL。

• 算子来历与参考文献 —— 该算子族所依据的研究/方法出处。

• 算法的正典(作者、年份)与用途见上面的族使用指南。

可运行的示例(实际调用该算子并已验证的样例)

• astro_stacking — py -3.11 examples/astro_stacking.py

• poc_exoplanet_transit — py -3.11 examples/poc_exoplanet_transit.py

• poc_print_registration — py -3.11 examples/poc_print_registration.py

类型可衔接的下一个算子(可接受 matrix 作为输入)

—

同类别(align)

align_frames


*Provenance: astrostack.py — ASTROSTACK 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.