wet_dry_inspection_pair — OPTICS watervision op

• Data kinds: image2d × image2d → table

• Call: import fullseye as fs; fs.ledger.wet_dry_inspection_pair(texture, defect_mask, roughness, water_film_um, light_deg, view_deg, n_water=None, seed=268, normal_sigma_px=2.0) -> 'dict' (implementation को सीधे call करना हो तो import watervision; watervision.wet_dry_inspection_pair(texture, defect_mask, roughness, water_film_um, light_deg, view_deg, n_water=None, seed=268, normal_sigma_px=2.0) -> 'dict', registry से लेना हो तो opsoptics.get("wet_dry_inspection_pair"))

उपयोग

एक ही बनावट वाली प्लेट को सूखी और गीली दशा में रेंडर करना, और दोनों में उसके दोष का contrast -> dict।

> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।

texture (H, W) in [0, 1] is the diffuse albedo of the plate and defect_mask (H, W, bool) marks the defect (at least one pixel inside and one outside). Both images use the per-pixel wet_surface_appearance for the diffuse part. The specular part uses a local normal: a Gaussian-smoothed random height map (seed, smoothing normal_sigma_px) whose slopes are scaled to an RMS slope per axis of roughness; each pixel mirrors the light with the Fresnel reflectance of its local incidence angle into the Gaussian lobe of wet_surface_appearance about the viewing direction, so a glint appears where the local normal bisects the light and the view and moves when light_deg changes. The dry and the wet plate share the normals, so they differ only by the film. light_deg is in the xz plane from the plate normal, the viewer on the other side at view_deg. The defect contrast is the Michelson contrast (mean_ok - mean_defect) / (mean_ok + mean_defect) of the region means, reported for the whole image and for the diffuse part alone. Because the film darkens dark pixels proportionally more (the factor (1 - r) / (1 - a r) grows with a), a dark defect on a brighter plate gains diffuse contrast when wet; the glints (shared by both regions) pull the total contrast the other way, so the table has both and predicted_diffuse_contrast_wet (the one-step prediction from the region mean albedos).

The table has dry, wet, diffuse_dry, diffuse_wet, specular_dry, specular_wet (images), contrast_dry, contrast_wet, contrast_diffuse_dry, contrast_diffuse_wet, predicted_diffuse_contrast_wet, coverage, glint_pixels_dry / glint_pixels_wet (pixels whose specular term exceeds the median diffuse albedo) and normals. A film of 0 gives identical images. Shapes that differ, a mask without both classes, textures outside [0, 1] or a negative film are refused.

पूरी family का input contract (fail-closed)

optics के सभी ops गणना से पहले input की जाँच करते हैं (कुछ भी चुपचाप पास नहीं होता):

• Unit argument के नाम में ही लिखी होती है — _mm / _um / _deg / _mrad। mm और µm की गड़बड़ी crash नहीं करती, बल्कि "सही दिखने वाला पर गलत उत्तर" देती है, इसलिए नाम से इसे रोका जाता है। मान के आकार से unit का अनुमान बिल्कुल नहीं लगाया जाता।

• String से ValueError — float('50') सफल हो जाता है, इसलिए बिना parse किया config value length के रूप में निकल जाता (मापा गया: thin_lens('50', '200') सही दिखने वाला 66.667 mm लौटा रहा था)। bool को भी True == 1 वाले implicit promotion के रूप में अस्वीकार किया जाता है।

• complex / masked array से ValueError (केवल real-valued slots; imaginary part को चुपचाप छोड़ना या mask हटाना अस्वीकार)। हर input पर NaN/Inf से ValueError।

• शून्य से भाग और उससे जुड़े मामलों को नाम लेकर अस्वीकार किया जाता है: focal length 0, radius of curvature 0, refractive index <= 0, पूरी तरह opaque aperture (सब 0, इसलिए normalisation 0/0), ऐसा PSF जिसका योग <= 0 हो, S0 = 0 वाला Stokes vector, और front focal point पर रखा object (image अनंत पर)।

• केवल 2 ops non-finite value लौटाते हैं, और वह भी contract के रूप में लिखा हुआ: depth_of_field hyperfocal distance से आगे far_mm = inf (hyperfocal distance की परिभाषा यही है) और gaussian_beam waist पर wavefront_radius_mm = inf (plane wavefront की radius of curvature)। दोनों साथ में एक finite साथी (far_is_infinite / curvature_per_mm) भी लौटाते हैं। इसके अलावा कोई भी चुपचाप आया NaN/Inf अंदर ही पकड़ा जाता है और ValueError देता है — "float64 overflow हुआ" और "उत्तर अनंत है" अलग-अलग दावे हैं, इसलिए पहले को दूसरे का चेहरा पहनाकर नहीं लौटाया जाता।

• Size की सीमा: generate होने वाले grid के लिए optics.MAX_GRID (4096), दिए गए field/PSF/aperture के लिए optics.MAX_FIELD_ELEMENTS (2^24), ABCD element chain के लिए optics.MAX_SYSTEM_ELEMENTS (1024), Zernike के लिए MAX_ZERNIKE_TERMS (512) / MAX_ZERNIKE_ORDER (40) / MAX_ZERNIKE_BASIS (2^25)। छोटे argument से बहुत बड़ा internal allocation होने वाले रास्तों (मापा गया: n_max=40 × 4096² पर 108 GB) को fail-closed ढंग से बंद किया गया है।

• भौतिक रूप से असंभव states भी अस्वीकार: degree of polarisation > 1 वाला Stokes vector, ऋणात्मक transmittance, ऋणात्मक intensity, और n-|m| odd जैसे अमान्य Zernike indices।

उपयोग की विस्तृत guide

• optics_imaging family guide

संदर्भ (sample data, साहित्य)

• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।

• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।

• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• poc_water_inspection_images — py -3.11 examples/poc_water_inspection_images.py

वे अगले ops जिनसे type जुड़ता है (table को input के रूप में लेते हैं)

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

इसी category के (watervision)

caustic_irradiance · bottle_image · fill_level_from_image · wet_surface_appearance · underwater_inspection_image · caustic_floor_segmentation


*Provenance: watervision.py — OPTICS operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

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