polarization_demosaic — OPTICS polarization op

数据种类:image2dpolsweep

调用: import fullseye as fs; fs.ledger.polarization_demosaic(raw, layout=((90.0, 45.0), (135.0, 0.0)))(要直接调用实现,import optics; optics.polarization_demosaic(raw, layout=((90.0, 45.0), (135.0, 0.0)));从台账取用则 opsoptics.get("polarization_demosaic"))

用法

将偏振传感器的马赛克拆成四张检偏器图像(0/45/90/135 度)。

> 以下的详细说明为原文 —— 摘要与标题已翻译。

A polarisation camera puts four micro-polarisers on each 2x2 block of

pixels; the raw frame is one (H, W) array in which neighbouring pixels saw

the scene through different analysers. This returns a `(4, H, W)` array

of images `[I_0, I_45, I_90, I_135] (the polsweep` sort, in

:data:POLARIZATION_SWEEP_ANGLES order, so the result feeds

:func:specularity.polarization_stokes and `polarization_dolp_map`

directly), each interpolated to full resolution.

Interpolation is bilinear, the same estimate a Bayer demosaic makes for

a colour plane that occupies one pixel in four: a missing pixel is the mean

of its measured 4-neighbours (edge-adjacent) or 4-neighbours (diagonal),

which is exactly the `[[1, 2, 1], [2, 4, 2], [1, 2, 1]] / 4` kernel applied

to the masked plane. Ground truth: on a plane that is linear in x and y

the interpolation is exact (a bilinear estimate of an affine field is the

field), so the test plants four affine fields, mosaics them, and demands

every returned image equal its field to 1e-12 away from the border. The

border is handled by mirroring the mosaic two pixels outward before

interpolating (an even, non-duplicating reflection keeps the 2x2 phase), so

a uniform field is exact up to the edge and a gradient is mirrored there —

a symmetric bias on the outermost row and column, and said so. Against

Polanalyser's OpenCV bilinear path the interior agrees to the 16-bit

quantisation (1.8e-5) and only the outer two pixels differ (2026-09-18).

*layout* is the angle at each 2x2 position, `((a00, a01), (a10, a11))` in

degrees; the default is the Sony IMX250MZR block. Every angle in

:data:POLARIZATION_SWEEP_ANGLES must appear exactly once.

Raises `ValueError`: *raw* is not a 2-D array, has an odd height or

width (the block would be cut), contains non-finite values, or *layout* is

not a permutation of the four sweep angles.

Provenance: the layout convention and the "four Bayer planes" reading of

the mosaic follow Polanalyser (Maeda, MIT); the interpolation is the

classic bilinear Bayer demosaic. This is a re-implementation from that

description, not copied code, and it does not depend on OpenCV. Colour

polarisation sensors (IMX250MYR, a 4x4 block) are handled by

:func:polarization_demosaic_color.

该族通用的输入契约(fail-closed)

optics 的每个算子都先校验输入再计算(不让任何东西无声通过):

单位写进参数名 —— _mm / _um / _deg / _mrad。把 mm 和 µm 弄混不会崩溃,而是给出「看着合理却是错的答案」,所以用命名来防。这里绝不从数值大小去猜单位。

• **字符串一律 ValueError** —— float('50') 会成功,于是未解析的配置值会被当成长度混进来(实测:thin_lens('50', '200') 曾返回看着合理的 66.667 mm)。bool 也按 True == 1 的隐式提升拒绝。

• **complex / masked array 一律 ValueError(仅接受实数槽位;拒绝无声丢弃虚部或剥掉掩码)。所有输入中的 NaN/Inf 一律 ValueError**。

逐项点名拒绝除零及其近亲:焦距 0、曲率半径 0、折射率 <= 0、全不透明光阑(全为 0,归一化变成 0/0)、总和 <= 0 的 PSF、S0 = 0 的 Stokes 矢量、物体位于前焦点(像在无穷远)。

只有两个算子会返回非有限值,而且都写进了契约:depth_of_field 在超焦距以外返回 far_mm = inf(这正是超焦距的定义),gaussian_beam 在束腰处返回 wavefront_radius_mm = inf(平面波前的曲率半径)。两者都同时返回一个有限的搭档(far_is_infinite / curvature_per_mm)。**除此之外的无声 NaN/Inf 都在内部检出并 ValueError** ——「float64 溢出了」和「答案是无穷大」是两种不同的主张,不能拿后者的脸去交付前者。

尺寸上限:生成网格受 optics.MAX_GRID(4096)限制,传入的场/PSF/光阑受 optics.MAX_FIELD_ELEMENTS(2^24),ABCD 元件序列受 optics.MAX_SYSTEM_ELEMENTS(1024),Zernike 受 MAX_ZERNIKE_TERMS(512)/ MAX_ZERNIKE_ORDER(40)/ MAX_ZERNIKE_BASIS(2^25)。以 fail-closed 堵住「小参数引发巨大内部分配」的路径(实测:n_max=40 × 4096² 需要 108 GB)。

物理上不可能的状态同样拒绝:偏振度 > 1 的 Stokes 矢量、负透过率、负强度、n-|m| 为奇数等非法 Zernike 指标。

详细使用指南

optics_imaging 族使用指南

参考(示例数据・文献)

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

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

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

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

polarization_camera_pipelinepy -3.11 examples/polarization_camera_pipeline.py

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

同类别(polarization)

jones_element · jones_apply · stokes_from_jones · mueller_element · mueller_apply · stokes_analyze · polarization_demosaic_color · mueller_from_intensities


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

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