# Direct Georeferencing with X,Y,Z and Omega, Phi, Kappa

I have images taken from plane, it's longitude, latitude, elevation, omega, phi, kappa. I suppose that earth is flat (I don't need any DEM on that stage) and I want to calculate how image is nailed to the ground. I want to find center and 4 corners of nailed image to the ground.

Could you advice some simple formula for calculation? Or free tool that has such calculations just to check my own implementation results. I tried to use GRASS but without any luck, it is too complicated :(

UPDATE: Images were taken from around 3.2k meters without physical GCPs. The precision that we got is around 20 meters with camera angles (Omega, Phi) around 2 grad. Do you think it is possible to get better precision? We are using C# and here is our implementation:

``````    /// <summary>
///
/// </summary>
/// <param name="omega">camera angle, in grads</param>
/// <param name="phi">camera angle, in grads</param>
/// <param name="kappa">camera angle, in grads</param>
/// <param name="longitude">camera position</param>
/// <param name="latitude">camera position</param>
/// <param name="altitude">camera position</param>
/// <param name="altOverGround">average flight height, it is defined on flight planning stage</param>
/// <param name="imageLength">it is defined on flight planning stage, calculated from altOverGround and focal lenght, it is in meters</param>
/// <param name="imageWidth">it is defined on flight planning stage, calculated from altOverGround and focal lenght, it is in meters</param>
/// <returns></returns>
public static DbGeography CalculateProjection(double omega, double phi, double kappa, double longitude, double latitude, double altitude,
double altOverGround, double imageLength, double imageWidth)
{
// coordinates of the camera
DbGeography cameraCoordinates = CreatePoint(longitude, latitude);

// get image center (projected to groud) as offset to camera coordinates
// result of imageCenter is in image coordinate system
Point imageCenter = GetImageCenter(omega, phi, kappa, altitude);

// calculating real image length for this height
var realImageLength = imageCenter.Z * imageLength / altOverGround;
var realImageWidth = imageCenter.Z * imageWidth / altOverGround;

// corners offset in image coordinates system
var xOfsfet = realImageLength / 2;
var yOffset = realImageWidth / 2;

// corners list
List<Point> imageCorners = new List<Point>() {
new Point(xOfsfet, yOffset, imageCenter.Z),
new Point(-xOfsfet, yOffset, imageCenter.Z),
new Point(-xOfsfet, -yOffset, imageCenter.Z),
new Point(xOfsfet, -yOffset, imageCenter.Z)
};

List<DbGeography> projectionCorners = new List<DbGeography>();
foreach (var point in imageCorners)
{
// get image corner projected to the ground
Point projectedPoint = GetProjectionCoordinates(omega, phi, kappa, altitude, point);

// add projected point to list of projected corners
}

// add first point to complete the polygon

return CreatePolygonFromListOfPoints(projectionCorners);
}

private static Point GetProjectionCoordinates(double omega, double phi, double kappa, double altitude, Point imageCorner)
{
// converting point coordinates from image's coordinate system to normal coordinate system
Point imagePoint = ConvertImageCoordToNormal(omega, phi, kappa, imageCorner);

// get coordinates of the projected point
return GetProjectionCoordinates(altitude, imagePoint);
}

private static Point GetProjectionCoordinates(double altitude, Point imagePoint)
{
var x = altitude * imagePoint.X / imagePoint.Z;
var y = altitude * imagePoint.Y / imagePoint.Z;
return new Point(x, y, altitude);
}

private static Point ConvertImageCoordToNormal(double omega, double phi, double kappa, Point imageCorner)
{
double x1, x2, y1, y2, z1, z2, x, y, z;
kappa = Math.PI / 2 - kappa;
x1 = imageCorner.X * Math.Cos(kappa) + imageCorner.Y * Math.Sin(kappa);
y1 = -imageCorner.X * Math.Sin(kappa) + imageCorner.Y * Math.Cos(kappa);
z1 = imageCorner.Z;

x2 = x1 * Math.Cos(phi) - z1 * Math.Sin(phi);
y2 = y1;
z2 = x1 * Math.Sin(phi) + z1 * Math.Cos(phi);

x = x2;
y = y2 * Math.Cos(omega) + z2 * Math.Sin(omega);
z = -y2 * Math.Sin(omega) + z2 * Math.Cos(omega);
return new Point(x, y, z);
}

/// <summary>
/// Calculates altitude of the image center
/// </summary>
/// <param name="omega"></param>
/// <param name="phi"></param>
/// <param name="kappa"></param>
/// <param name="altitude"></param>
/// <returns>Altitude of image center</returns>
private static Point GetImageCenter(double omega, double phi, double kappa, double altitude)
{
// calculating coordinates of image center
var xCenter = altitude * Math.Tan(phi);
var yCenter = altitude * Math.Tan(omega);
var imageAltitude = altitude / (Math.Cos(omega) * Math.Cos(phi));

// recalculating center with kappa value
var alpha = Math.Atan(yCenter / xCenter) + kappa;
var aa = Math.Sqrt(xCenter * xCenter + yCenter * yCenter);

double imageCenterX = Math.Cos(alpha) * aa;
double imageCenterY = Math.Sin(alpha) * aa;
return new Point(imageCenterX, imageCenterY, imageAltitude);
}

{
omega = Math.PI * omega / 200;
return omega;
}
``````

and Point class:

``````class Point
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Point(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
}
``````
• – whuber Dec 26 '13 at 15:46
• Updated first post with C# implementation. Any help to increase accuracy is appreciated! Thanks! – Serhiy Zhdynyak Dec 27 '13 at 14:13
• any idea how you could convert heading, pitch, roll to omega, phi, kappa? – bozdoz Mar 30 at 18:48