如何将180°视场鱼眼图像局部正确投影至3D半球?
Great question—projecting your 180° FOV fisheye circle onto a 3D hemisphere is a smart, geometrically sound approach for local undistortion, especially since you already have the critical parameters (center coordinates and circle radius) at hand. Let’s walk through the implementation step by step, with clear math and practical code-ready logic:
First, convert raw pixel positions into normalized polar coordinates relative to the fisheye circle's center:
For any pixel (x, y) inside the fisheye circle:
- Calculate offset from the circle center:
dx = x - cx,dy = y - cy - Compute the pixel's polar radius:
r_pixel = sqrt(dx² + dy²) - Normalize the radius to a [0, 1] range:
r_norm = r_pixel / R(whereRis the circle's radius) - Map the normalized radius to a polar angle
θ: since a 180° FOV covers a full hemisphere,θranges from 0 (center, optical axis) to π/2 (circle edge). For an equidistant fisheye projection (the most common for 180° FOV), useθ = (π/2) * r_norm - Compute the azimuth angle
φ:φ = arctan2(dy, dx)
Convert the polar angles to 3D Cartesian coordinates (assuming the fisheye's optical axis aligns with the hemisphere's z-axis):
x3d = sin(θ) * cos(φ) y3d = sin(θ) * sin(φ) z3d = cos(θ)
This places every fisheye pixel on the surface of a unit hemisphere facing along the z-axis.
To correct a local region, you’ll project a subset of the hemisphere onto a virtual perspective camera plane:
- Choose a focal length
ffor the corrected region: adjust this to control the FOV (e.g., for a 60° FOV, usef = 1 / tan(30°)≈ 1.732) - Set a center point
(u0, v0)for your corrected output image (align this with the center of your desired undistorted region)
Avoid empty pixel "holes" by using inverse mapping: for each pixel (u, v) in your corrected local image, find its corresponding position in the original fisheye:
- Normalize the output pixel coordinates relative to the virtual camera:
u_norm = (u - u0) / f v_norm = (v - v0) / f - Compute the corresponding 3D point on the hemisphere (using perspective projection constraints):
z3d = 1 / sqrt(u_norm² + v_norm² + 1) x3d = u_norm * z3d y3d = v_norm * z3d - Convert back to fisheye polar coordinates:
θ = arccos(z3d) φ = arctan2(y3d, x3d) - Map back to the original fisheye's pixel coordinates:
r_pixel = (θ / (π/2)) * R # Scale θ back to the fisheye's pixel radius range x = cx + r_pixel * cos(φ) y = cy + r_pixel * sin(φ) - Use bilinear interpolation to fetch the pixel value from the original fisheye image at the floating-point position
(x, y), then assign it to(u, v)in the corrected image.
- Projection Model Adjustment: If your fisheye uses an equisolid angle projection (another common 180° FOV model), update the
θmapping toθ = 2 * arcsin(r_norm)instead of the equidistant formula. - Boundary Handling: Ignore or fill with a neutral color (e.g., black) any corrected pixels that map to positions outside the original fisheye circle.
- Interpolation: Always use bilinear or bicubic interpolation—nearest-neighbor sampling will result in jagged, pixelated edges.
- ROI Size: Keep your local undistortion region small; large areas will show noticeable perspective stretching, which undermines the goal of natural-looking local correction.
内容的提问来源于stack exchange,提问作者VideoProcessingResearcher

