Angular Fisheye Image Mapping: 3D point ⟹ pixel


Image fishEyeImage;
fishEyeImage.load( "RenderedImageUsingFisheyeLens.exr" );

// given data
Point worldPoint = ...;
Point worldCameraPosition = ...;
Point worldAimingPoint = ...;

// the assumption in this example)
// the camera's up vector = world y-axis
Vector upVector = Vector( 0.0, 1.0, 0.0 );

// three orthogonal unit axes of the camera space
// xAxis: right vector
// yAxis: up vector
// zAxis: viewing direction
Vector zAxis = Normalize( worldAimingPoint - worldCameraPosition );
Vector xAxis = Normalize( Cross( zAxis, upVector ) );
Vector yAxis = Normalize( Cross( xAxis, zAxis ) );

// the unit directional vector
// from the cameraPosition to the point on the unit sphere
// the center of the sphere = worldCameraPosition
Vector direction = Normalize( worldPoint - worldCameraPosition );

// the coordinates of its end point
// on the xy-plane of the camera space
double xValue = Dot( direction, xAxis );
double yValue = Dot( direction, yAxis );

// the projected directional vector
// onto the xy-plane of the camera space
Vector projectedDirection = ( xValue * xAxis ) + ( yValue * yAxis );

// the angle between projectedDirection and direction
// cos(theta) = Length(projectedDirection) / Length(direction)
// and the denominator Length(direction) = 1.0
// direction = forward: theta = pi/2
// direction = right or left: theta = 0.0
double theta = acos( Length( projectedDirection ) );

// scaling factor to image space
// the range of theta: pi/2 (forward) ~ 0.0 (right/left)
// the range of alpha: 0.0 (forward) ~ 1.0 (right/left)
double alpha = 1.0 - theta / ( 0.5 * PI );

// the vector from the image center to the pixel
Vector pixelDirection = Normalize( projectedDirection ) * alpha;

// xy coordinates: -1.0 ~ +1.0
// origin: center
// x-direction: right
// y-direction: up
double x = Dot( projectedDirection, xAxis );
double y = Dot( projectedDirection, yAxis );

// st coordinates: 0.0 ~ 1.0
// origin: bottom-left
// s-direction: right
// t-direction: up
double s = ( 0.5 * x ) + 0.5;
double t = ( 0.5 * y ) + 0.5;

// Now, we are ready to get the pixel color.
// why 1.0 - t rather than just t?
// because the origin of an image: top-left
Color pixelValue = fisheyeImage.get( s, 1.0 - t );

Add a Comment