drizzle_resample — ASTROSTACK stack op

• 数据种类:images → image2d

• 调用: import fullseye as fs; fs.ledger.drizzle_resample(frames, shifts=None, scale=2.0, pixfrac=1.0)(要直接调用实现,import astrostack; astrostack.drizzle_resample(frames, shifts=None, scale=2.0, pixfrac=1.0);从台账取用则 opsastrostack.get("drizzle_resample"))

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

• 底层返回: (sci, wht) -> image2d

用法

Drizzle —— 由若干亚像素错位的帧构建更细的网格(保面积)。

Fruchter & Hook, *Drizzle: A Method for the Linear Reconstruction of Undersampled Images*, PASP 114, 144 (2002)。把输入像素看作缩小一圈的 “液滴(drop,边长 pixfrac)”,按其与输出网格像素的重叠面积 成比例地分配通量。由于不做插值,

• 总通量守恒。 只要液滴落在输出网格内部,sci.sum() 就与各输入帧总和的平均值严格一致(实测:shifts=0、scale=2、pixfrac=0.7 时相对误差 0.0)。这就是把它做成仅凭返回值即可验算的形式的原因。

• pixfrac 越小,液滴落在单个输出像素内部的比例越大,分辨率提高,但会出现未被覆盖的输出像素(wht 在那里变小)。这种拉锯是 drizzle 唯一的调节点。

只有在采样不足时才有效,这是实测的结论。48x48 中 10 颗星、抖动 1.5 px、16 帧的测量(数值为换算到输入像素的 FWHM)::

真实 FWHM 单帧 直接平均 drizzle x2 (pixfrac=0.5)

1.0 1.773 2.249 1.312

1.3 1.929 2.876 1.572

1.8 2.262 2.648 3.086

2.5 4.057 4.295 3.586

只有在 FWHM 低于 2 像素(违反奈奎斯特)的地方 drizzle 才胜出。抖动后的帧直接平均反而会使像变钝(1.773 → 2.249) —— 因为偏移被平均掉了,而 drizzle 把同样的偏移转化为分辨率。在 1.8 px 以上已经充分采样,drizzle 得不到好处,只会损失液滴卷积的那部分。

看两颗星能否分开最直观。将 σ=0.55 px 的 2 颗星以不同间隔抖动拍摄 16 帧,分别用平均合成和 drizzle x3 (pixfrac=0.4) 后做 star_detect 的实测:间隔 1.6 输入像素时,平均合成找到 1 颗,drizzle 找到 2 颗(2.0 px 以上两者都是 2 颗)。

*shifts* 是 (N, 2) 的 (dr, dc),表示帧 i 相对基准偏移了多少(synth_frame_series 的 truth["shifts"] 就是这个方向)。None 则全部为 0。

★ 注意符号 —— frame_align / align_frames 返回的矩阵中的平移是“把帧拉回基准”的方向,即与这里需要的 (dr, dc) 符号相反。若直接传入估计值,偏移不会被抵消反而加倍,也不抛异常地产生双像(实测:6 帧 96x96 时 est + truth ≈ 0,直接传入残差为 2 倍)。要从矩阵得到方向正确的 shifts,请使用 drizzle_shifts。不接受旋转 —— 一旦有旋转,各轴不再可分,重叠面积无法写成闭式,

所以请先用 align_frames 还原(在那里付出插值误差,让这笔交易可见更为诚实)。

★ 输入像素落到输出的哪里(此前没有写明这一约定)。按像素中心之间的对应::

out = in * scale + (scale - 1) / 2

scale=2 时,输入 (8, 8) 处的星位于输出 (16.5, 16.5)。输入像素 in 所占区间 [in, in+1) 映射到输出的 [in*scale, (in+1)*scale),其中心就是上式 —— 而不是简单的 in*scale。若丢掉半个像素,scale=4 时会产生 1.5 个输出像素、折合输入 0.375 像素的系统偏移,配准后的测光和双星间距都会因此悄悄出错。

实测(24x24、单像素星、pixfrac=1、用质心测量):scale 为 2 / 3 / 4 时与上式之差严格为 0。scale=2.5 时偏移 0.05 个输出像素,但这不是公式错误,而是因为边缘输出像素只被部分覆盖,下标的质心与连续量的质心之间产生偏差(整数倍时不会出现这一零头)。需要严格处理位置时请使用整数 scale。

Returns (sci, wht):

• sci —— (round(H*scale), round(W*scale)) float64,总通量单位(与输入相同的电子数)。落到网格外的液滴会使总和减少,因此 sci.sum() 与输入总和之差正是“边缘损失的量”。

• wht —— 同形状的权重图,表示输出像素被多少份液滴覆盖(输出像素面积记为 1)。pixfrac=1 且 shifts=0 时内部严格为 1.0。

★ 观看 / 测量时请使用 sci / wht。 sci 为了守恒总通量,原样保存“分配的量”,覆盖的不均匀会残留在像中。pixfrac 较小时覆盖呈网格状不均,对原始 sci 做检测,这个网格就会变成星 —— 实测(scale=3、pixfrac=0.4、1 对双星 24 帧)中,star_detect 对原始 sci 返回了 200 个(顶到上限),对 sci / wht 则正确地返回 2 个。守恒量(sci)与外观(sci / wht)是不同的量,用一个代替另一个毫无例外地会出错。

Raises ValueError:*frames* 不是 list / tuple / 形状不一致 / *scale* 小于 1 / *pixfrac* 不在 (0, 1] 内 / *shifts* 的形状不是 (N, 2) / 输出超过 MAX_OUTPUT_ELEMENTS 时。

参考(示例数据、文献)

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

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

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

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

• astro_stacking — py -3.11 examples/astro_stacking.py

• poc_astro_photometry — py -3.11 examples/poc_astro_photometry.py

• poc_superresolution_limits — py -3.11 examples/poc_superresolution_limits.py

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

frame_quality · noise_sigma · cosmic_ray_reject · star_detect · psf_fit · aperture_photometry · frame_align

同类别(stack)

sigma_clip_stack


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

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