bottle_image — OPTICS watervision op

• 資料種類:無 → table(僅由參數決定的運算子 —— 不接受影像或資料輸入)

• 呼叫: import fullseye as fs; fs.ledger.bottle_image(radius_mm, wall_mm, height_mm, fill_fraction, n_glass, n_liquid, meniscus_mm=0.0, bubbles=None, camera_distance_mm=500.0, pixel_pitch_um=20.0, size=None, light='backlight', n_air=1.0) -> 'dict'(要直接呼叫實作,import watervision; watervision.bottle_image(radius_mm, wall_mm, height_mm, fill_fraction, n_glass, n_liquid, meniscus_mm=0.0, bubbles=None, camera_distance_mm=500.0, pixel_pitch_um=20.0, size=None, light='backlight', n_air=1.0) -> 'dict';從台帳取用則 opsoptics.get("bottle_image"))

• GPU:無(僅 CPU 參考實作)

用法

部分裝有液體的圓柱形瓶子的側視圖,逐行進行光線追跡 -> 字典。

> 以下的詳細說明為原文 —— 摘要與標題已翻譯。

The bottle (outer radius radius_mm, glass wall wall_mm, height height_mm, axis vertical, base at z = 0) is looked at by a pinhole camera camera_distance_mm from the axis. Every image row is the horizontal cross-section at its height: the ray of a pixel is traced through the circles of the section (outer wall, inner wall, the edge of the liquid in a meniscus row, bubbles) with the vector form of Snell's law and the unpolarised Fresnel transmittance at each interface. Total internal reflection reflects the ray (at most 24 interface events are followed; a ray still wandering then is counted in unresolved_rays and left dark). The liquid (n_liquid) fills the bottle up to fill_fraction * height_mm; meniscus_mm lets it climb the wall by that much as (rho / r_inner)^6. bubbles is a list of (x_mm, z_mm, r_mm) (or with a fourth y_mm along the viewing axis; default 0): air spheres in the liquid, drawn as their circle in each row they cross. pixel_pitch_um is the sampling pitch in the plane of the axis, so 1000 / pixel_pitch_um pixels are 1 mm there; size is (rows, cols) (default: the rows exactly cover the height, the width is 1.15 times the diameter); row j is at z = height - (j + 0.5) pitch.

light="backlight": a diffuse panel of radiance 1 behind the bottle that emits only within +-8 degrees of the viewing axis (soft edge 1 degree): a pixel is lit when its ray leaves the bottle inside that cone, times the product of the Fresnel transmittances. The empty bottle bends rays little and is lit to near the edges; the filled one is a cylindrical lens, so only a central band (half width alpha / (1/f - 1/dc) with the paraxial focal length f of watermedia.cylinder_lens_caustic) is lit and the flanks go dark; an air bubble in the liquid is a diverging lens and shows as a dark ring. light="frontlight": a matt wall of radiance 0.8 behind, a dim dome plus a soft box at 35 degrees, and the first Fresnel reflection of the outer wall (R times the environment radiance), which gives the glint and the bright rim at grazing view. Interior reflections other than total internal reflection are not followed, the rows are independent (no vertical refraction at the shoulder or the base), and rows without bubbles or meniscus are computed once per kind (the empty and the full section), so rows of equal geometry are bit identical.

The table has image (rows, cols; no pixel exceeds 1), x_mm, z_mm, pixel_pitch_mm, magnification_px_per_mm, fill_row_from_top (the first liquid row), liquid_rows (rows with liquid; about fill_fraction height / pitch), fill_z_mm, paraxial_efl_mm and band_half_width_mm_paraxial (the predicted half width of the lit band of the filled bottle, inf when the lens does not converge within the camera distance), central_transmittance_empty / ..._filled (the product of the normal-incidence Fresnel transmittances of the four interfaces on the axis), unresolved_rays and the inputs echoed. n_glass <= 1, n_liquid <= 1, n_air < 1 or not below both, a fill outside [0, 1], a wall not thinner than the radius, a meniscus that does not fit and a bubble outside the liquid are refused.

該族通用的輸入契約(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。

• 運算子來歷與參考文獻 —— 該運算子族所依據的研究/方法出處。

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

可執行的範例(實際呼叫該運算子並已驗證的樣例)

• poc_water_inspection_images — py -3.11 examples/poc_water_inspection_images.py

型別可銜接的下一個運算子(可接受 table 作為輸入)

abcd_matrix · wavefront_stats · sfr_from_edge · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd

同類別(watervision)

caustic_irradiance · fill_level_from_image · wet_surface_appearance · wet_dry_inspection_pair · underwater_inspection_image · caustic_floor_segmentation


*Provenance: watervision.py — OPTICS 運算子登記表。本條目由 tools/opdocs.py md 自動產生(請勿手動編輯)。*

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