range_image op• Data kinds: depth → normalmap
• Call: import fullseye as fs; fs.ledger.normals_from_depth(depth, fx=None, fy=None, cx=None, cy=None, orient_to_camera=True, spacing=None) (implementation को सीधे call करना हो तो import range_image; range_image.normals_from_depth(depth, fx=None, fy=None, cx=None, cy=None, orient_to_camera=True, spacing=None), registry से लेना हो तो ops3d.get("normals_from_depth"))
organized depth → oriented unit normals (H,W,3)। पड़ोसी pixels के 3D points का cross product (grid structure का उपयोग, O(HW))।
fx,fy देने पर perspective, न देने पर orthographic। orient_to_camera=True पर normals का sign camera (origin) की ओर एक-समान किया जाता है।
★इसी नाम का एक अलग function 1-line facade में है। fullseye.normals_from_depth (depth, K, smooth=0) वाला perspective version है जिसमें K ज़रूरी है, जबकि यह वाला (fullseye.ledger के ज़रिए = range_image) K न लेने वाला orthographic version है। एक का call तरीका याद करने पर, दूसरे में TypeError आता है (2026-09-08 को मापा गया)।
★spacing=(dy, dx) orthographic mode में pixel का असली आकार है। default None का मतलब "1 pixel = 1 unit" है, और anisotropic grid (जैसे column 0.05 mm × row 0.5 mm) को सीधे देने पर slope चुपचाप खिसक जाता है —— मापने पर x component 20 गुना (= 1/dx गुना) गलत था, और न exception आया न warning। असली आकार पता हो तो इसे ज़रूर दें। perspective mode (fx/fy दिए हों) में focal length असली आकार तय करती है, इसलिए इसे अनदेखा किया जाता है। ★spacing देते समय orient_to_camera=False रखें। orthographic में "camera" बस origin (ऊपर बायाँ कोना, depth 0) की एक सुविधाजनक कल्पना है; असली आकार डालने पर surface के सापेक्ष उसकी स्थिति बदल जाती है और sign उलट सकता है (मापा गया: slope 0.1 वाले plane पर orient_to_camera=False से true value x=-0.0995 मिलता है, True से +0.0995)। दिशा चाहिए तो बाद के चरण में ऐसे coordinate system में मिलाएँ जहाँ line of sight परिभाषित हो।
normal पड़ोसी pixels के cross product से निकलता है, इसलिए दोनों axes पर neighbours चाहिए। H<2 or W<2 में 2nd tangent direction नहीं होती और normal परिभाषित नहीं होता (उस axis के gradient को 0 मानने पर cross(dPx,0)=[0,0,0] का degenerate normal चुपचाप लौट आता)। इसलिए fail-closed तरीके से साफ़ ValueError के साथ अस्वीकार किया जाता है।
गणना में depth_to_organized_points से 3-D points P बनाए जाते हैं, और np.gradient के column-direction difference dPx और row-direction difference dPy का cross product dPx × dPy unit length पर लाया जाता है (किनारों पर one-sided difference)। orient_to_camera=True में n·(-P) < 0 वाले pixels को उलटा जाता है, ताकि normals origin (camera) की ओर रहें। orthographic mode (fx या fy None) में P=(u,v,d) होता है, इसलिए origin image के ऊपर बाएँ depth 0 पर होता है, और ध्यान दें कि "camera की ओर" का अर्थ perspective mode से अलग है। cx और cy छोड़ने पर image center लिया जाता है। depth के step (occlusion edge) को पार करने वाले pixels पर cross product step की दिशा पकड़ लेता है और normal बिगड़ जाता है, इसलिए पहले occlusion_edges से boundary pixels हटाकर इस्तेमाल करें। depth 0 / NaN वाले pixels की जाँच नहीं होती और उनका normal भी अनिश्चित रहता है। return value float32 (H,W,3) है।
• blender_interop — Blender के साथ उपयोग — shape बनाएँ, fullseye से मापें (सावधानियाँ: axes, units, ground truth)
• depth_sensors — Depth sensors — ranging के सिद्धांत, असली devices के आँकड़े, dropouts कैसे दिखते हैं
• 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 के स्रोत।
• range_image — py -3.11 examples_3d/range_image.py
normalmap को input के रूप में लेते हैं)fuse_to_voxel · render_shaded · phong_shade · matcap_shade · brdf_lommel_seeliger · brdf_hapke · bump_normals_fbm · integrate_normals
range_image)depth_to_organized_points · occlusion_edges · bearing_angle_image
*Provenance: range_image.py — 3D operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.