Extension Name E57_LEICA_Camera_Distortion XML namespace DIST xmlns:dist="http://www.libe57.org/E57_LEICA_Camera_Distortion.txt" Contact Aldo Facchin, Leica GeoSystems (aldo . facchin @ leica-geosystems.com) Stan Coleby, Cerisoft LLC (stan . coleby @ gmail.com) Contributors none. Version Last Modified Date: October 3, 2014 Revision: 1 Dependencies none. Overview This extension adds camera distortion to the pinhole camera model. This allows the camera image to be stored in the original form and allows the image corrections to be done by the user if that user needs to overlay the image on the point data. However, many applications only want the original photographs, positions, directions, timestamps, and doesn't need to do the overlaya such as in mobile scanning applications. IP Status No known IP claims. New Fields none. New PointRecord Fields none. New Fields none. New Fields Element Name Type Description "dist:distortion" Structure Image camera distortion structure "dist:CameraNumber" Integer Optional - Camera number in a multiple camera app (1 - n). "dist:Type" String Distortion Type like "OpenCV" "dist:CV_K1" Float radial distortion coefficients. "dist:CV_K2" Float radial distortion coefficients. "dist:CV_K3" Float radial distortion coefficients. "dist:CV_K4" Float radial distortion coefficients. "dist:CV_K5" Float radial distortion coefficients. "dist:CV_K6" Float radial distortion coefficients. "dist:CV_P1" Float tangential distortion coefficients. "dist:CV_P2" Float tangential distortion coefficients. "dist:CV_CX" Float principal point usually at image centerX in pixel units. "dist:CV_CY" Float principal point usually at image centerY in pixel units. "dist:CV_FX" Float X focal lengths expressed in pixel units. "dist:CV_FY" Float Y focal lengths expressed in pixel units. "dist:CV_HEIGHT" Integer image X in pixel units. "dist:CV_WIDTH" Integer image Y in pixel units. The camera distortion information is unique for each camera used. However, in order for each image to standard on its own, this distortion data should be included with each "image2D" data struction for each jpgs. The Optional CameraNumber is a 1 to n camera position used in mobil scanners to indicate which camera was used. The writer should include each image in sequence that was taken at the same time i.e. camera 1, camera 2,.. camera n, camera 1 from next position or timestampe etc. XML Example ... 1 -1.7010328174209699e-001 1.12322889607517e-001 -1.77362716988726e-002 8.0965912894873104e-004 6.8468997337824003e-005 1.0097520611508299e+003 1.03193331309306e+003 1.5040567047204299e+003 1.5040567047204299e+003 2000 2000 ... Sample Code ////////////////////////////////// // Writing Extension declaration// ////////////////////////////////// // FoundationAPI _imf.extensionsAdd("dist","http://www.libe57.org/E57_DIST_Camera_Distortion.txt"); ... // Sample API e57::Writer pWriter(...); pWriter.GetRawIMF().extensionsAdd("dist","http://www.libe57.org/E57_DIST_Camera_Distortion.txt"); /////////////////////////////// // Write distortion ////////////////////////////// //Given good distortion data integer cameraNumber = 1; ustring distortionType = "OpenCV"; integer imageX = ..; integer imageY = ..; double CV_K1 = ..; double CV_K2 = ..; double CV_K3 = ..; double CV_K4 = ..; double CV_K5 = ..; double CV_K6 = ..; double CV_P1 = ..; double CV_P2 = ..; double CV_CX = ..; double CV_CY = ..; double CV_FX = ..; double CV_FY = ..; integer imageIndex = ..; Get the image index ... // Sample API ImageFile _imf = pWriter.GetRawIMF(); VectorNode _images2D = pWriter.GetRawImages2D(); if( (imageIndex < 0) || (imageIndex >= _images2D.childCount())) return false; // Both API //access the image2D structure StructureNode image(_images2D.get(imageIndex)); StructureNode distortion = StructureNode(_imf); image.set("dist:distortion", distortion); distortion.set("dist:CameraNumber", IntegerNode(imf, cameraNumber, NULL, 100)); distortion.set("dist:Type", StringNode(imf, distortionType.c_str())); distortion.set("dist:CV_K1", FloatNode(imf, CV_K1)); distortion.set("dist:CV_K2", FloatNode(imf, CV_K2)); distortion.set("dist:CV_K3", FloatNode(imf, CV_K3)); distortion.set("dist:CV_K4", FloatNode(imf, CV_K4)); distortion.set("dist:CV_K5", FloatNode(imf, CV_K5)); distortion.set("dist:CV_K6", FloatNode(imf, CV_K6)); distortion.set("dist:CV_P1", FloatNode(imf, CV_P1)); distortion.set("dist:CV_P2", FloatNode(imf, CV_P2)); distortion.set("dist:CV_CX", FloatNode(imf, CV_CX)); distortion.set("dist:CV_CY", FloatNode(imf, CV_CY)); distortion.set("dist:CV_FX", FloatNode(imf, CV_FX)); distortion.set("dist:CV_FY", FloatNode(imf, CV_FY)); distortion.set("dist:CV_WIDTH", IntegerNode(imf, CV_WIDTH)); distortion.set("dist:CV_HEIGHT", IntegerNode(imf, CV_HEIGHT)); /////////////////////////// //Read distortion data ///////////////////////// // Sample API e57::Reader pReader(....); ... VectorNode _images2D = pReader.GetRawImages2D(); if( (imageIndex < 0) || (imageIndex >= images2D.childCount())) return false; // Both API //access the image2D structure StructureNode image(_images2D.get(imageIndex)); ustring url; if (pReader.GetRawIMF().extensionsLookupPrefix("dist", url)) { if(image.isDefined("dist:distortion")) { StructureNode distortion(image.get("dist:distortion")); if(distortion.isDefined("dist:CameraNumber")) cameraNumber = (long) IntegerNode(distortion.get("dist:CameraNumber")).value(); if(distortion.isDefined("dist:Type")) distortionType = StringNode(distortion.get("dist:Type")).value().c_str(); if(distortion.isDefined("dist:CV_K1")) CV_K1 = FloatNode(distortion.get("dist:CV_K1")).value(); if(distortion.isDefined("dist:CV_K2")) CV_K2 = FloatNode(distortion.get("dist:CV_K2")).value(); if(distortion.isDefined("dist:CV_K3")) CV_K3 = FloatNode(distortion.get("dist:CV_K3")).value(); if(distortion.isDefined("dist:CV_K4")) CV_K4 = FloatNode(distortion.get("dist:CV_K4")).value(); if(distortion.isDefined("dist:CV_K5")) CV_K5 = FloatNode(distortion.get("dist:CV_K5")).value(); if(distortion.isDefined("dist:CV_K6")) CV_K6 = FloatNode(distortion.get("dist:CV_K6")).value(); if(distortion.isDefined("dist:CV_P1")) CV_P1 = FloatNode(distortion.get("dist:CV_P1")).value(); if(distortion.isDefined("dist:CV_P2")) CV_P2 = FloatNode(distortion.get("dist:CV_P2")).value(); if(distortion.isDefined("dist:CV_CX")) CV_CX = FloatNode(distortion.get("dist:CV_CX")).value(); if(distortion.isDefined("dist:CV_CY")) CV_CY = FloatNode(distortion.get("dist:CV_CY")).value(); if(distortion.isDefined("dist:CV_FX")) CV_FX = FloatNode(distortion.get("dist:CV_FX")).value(); if(distortion.isDefined("dist:CV_FY")) CV_FY = FloatNode(distortion.get("dist:CV_FY")).value(); if(distortion.isDefined("dist:CV_HEIGHT")) CV_HEIGHT = IntegerNode(distortion.get("dist:CV_HEIGHT")).value(); if(distortion.isDefined("dist:CV_WIDTH")) CV_WIDTH = IntegerNode(distortion.get("dist:CV_WIDTH")).value(); } } Issues none ASTM E57 Listed Submitted Date: October 10, 2014 Revision History Revision 1, 2014/10/03 - Initial version of this document Copyright Copyright (c) 2014 Aldo Facchin Leica GeoSystems(aldo . facchin @ leica-geosystems.com), All Rights Reserved. Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this extension and accompanying documentation covered by this license (this "Extension") to use, reproduce, display, distribute, execute, and transmit this Extension, and to prepare derivative works of this Extension, and to permit third-parties to whom this Extension is furnished to do so, all subject to the following: The copyright notices in this Extension and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of this Extension, in whole or in part, and all derivative works of this Extension, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. Disclaimer THIS EXTENSION IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THIS EXTENSION BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS EXTENSION OR THE USE OR OTHER DEALINGS IN THIS EXTENSION.