odm_orthophoto refactoring

Former-commit-id: 28b7f009b0
pull/1161/head
Piero Toffanin 2019-12-17 16:21:42 -05:00
rodzic 6e1a837485
commit 0664fdcb9f
2 zmienionych plików z 52 dodań i 384 usunięć

Wyświetl plik

@ -1,58 +1,18 @@
// C++
#include <math.h>
#include <sstream>
#include <fstream>
#include <Eigen/StdVector>
// This
#include "OdmOrthoPhoto.hpp"
std::ostream & operator<< (std::ostream &os, const WorldPoint &worldPoint)
{
return os << worldPoint.eastInteger_ + worldPoint.eastFractional_ << " " << worldPoint.northInteger_ + worldPoint.northFractional_;
}
std::istream & operator>> (std::istream &is, WorldPoint &worldPoint)
{
is >> worldPoint.eastInteger_;
// Check if east coordinate is given as rational.
if('.' == is.peek())
{
is >> worldPoint.eastFractional_;
}
else
{
worldPoint.eastFractional_ = 0.0f;
}
is >> worldPoint.northInteger_;
// Check if north coordinate is given as rational.
if('.' == is.peek())
{
is >> worldPoint.northFractional_;
}
else
{
worldPoint.northFractional_ = 0.0f;
}
return is;
}
OdmOrthoPhoto::OdmOrthoPhoto()
:log_(false)
{
inputGeoRefFile_ = "";
inputTransformFile_ = "";
outputFile_ = "ortho.jpg";
:log_(false){
outputFile_ = "ortho.tif";
logFile_ = "log.txt";
outputCornerFile_ = "";
transformOverride_ = false;
resolution_ = 0.0f;
boundaryDefined_ = false;
boundaryPoint1_[0] = 0.0f; boundaryPoint1_[1] = 0.0f;
boundaryPoint2_[0] = 0.0f; boundaryPoint2_[1] = 0.0f;
boundaryPoint3_[0] = 0.0f; boundaryPoint3_[1] = 0.0f;
@ -139,55 +99,6 @@ void OdmOrthoPhoto::parseArguments(int argc, char *argv[])
ss >> resolution_;
log_ << "Resolution count was set to: " << resolution_ << "pixels/meter\n";
}
else if(argument == "-boundary")
{
if(argIndex+8 >= argc)
{
throw OdmOrthoPhotoException("Argument '" + argument + "' expects 8 more input following it, but no more inputs were provided.");
}
std::stringstream ss;
ss << argv[argIndex+1] << " " << argv[argIndex+2] << " " << argv[argIndex+3] << " " << argv[argIndex+4] << " " << argv[argIndex+5] << " " << argv[argIndex+6] << " " << argv[argIndex+7] << " " << argv[argIndex+8];
ss >> worldPoint1_ >> worldPoint2_ >> worldPoint3_ >> worldPoint4_;
boundaryDefined_ = true;
argIndex += 8;
log_ << "Boundary point 1 was set to: " << worldPoint1_ << '\n';
log_ << "Boundary point 2 was set to: " << worldPoint2_ << '\n';
log_ << "Boundary point 3 was set to: " << worldPoint3_ << '\n';
log_ << "Boundary point 4 was set to: " << worldPoint4_ << '\n';
}
else if(argument == "-boundaryMinMax")
{
if(argIndex+4 >= argc)
{
throw OdmOrthoPhotoException("Argument '" + argument + "' expects 4 more input following it, but no more inputs were provided.");
}
std::stringstream ss;
ss << argv[argIndex+1] << " " << argv[argIndex+2] << " " << argv[argIndex+3] << " " << argv[argIndex+4];
ss >> worldPoint1_ >> worldPoint3_;
boundaryDefined_ = true;
// Set the other world points as the other two corners.
worldPoint2_.eastFractional_ = worldPoint1_.eastFractional_;
worldPoint2_.eastInteger_ = worldPoint1_.eastInteger_;
worldPoint2_.northFractional_ = worldPoint3_.northFractional_;
worldPoint2_.northInteger_ = worldPoint3_.northInteger_;
worldPoint4_.eastFractional_ = worldPoint3_.eastFractional_;
worldPoint4_.eastInteger_ = worldPoint3_.eastInteger_;
worldPoint4_.northFractional_ = worldPoint1_.northFractional_;
worldPoint4_.northInteger_ = worldPoint1_.northInteger_;
argIndex += 4;
log_ << "Boundary point 1 was set to: " << worldPoint1_ << '\n';
log_ << "Boundary point 2 was set to: " << worldPoint2_ << '\n';
log_ << "Boundary point 3 was set to: " << worldPoint3_ << '\n';
log_ << "Boundary point 4 was set to: " << worldPoint4_ << '\n';
}
else if(argument == "-verbose")
{
log_.setIsPrintingInCout(true);
@ -221,16 +132,6 @@ void OdmOrthoPhoto::parseArguments(int argc, char *argv[])
inputFiles.push_back(item);
}
}
else if(argument == "-inputGeoRefFile")
{
argIndex++;
if (argIndex >= argc)
{
throw OdmOrthoPhotoException("Argument '" + argument + "' expects 1 more input following it, but no more inputs were provided.");
}
inputGeoRefFile_ = std::string(argv[argIndex]);
log_ << "Reading georef from: " << inputGeoRefFile_ << "\n";
}
else if(argument == "-outputFile")
{
argIndex++;
@ -251,17 +152,6 @@ void OdmOrthoPhoto::parseArguments(int argc, char *argv[])
outputCornerFile_ = std::string(argv[argIndex]);
log_ << "Writing corners to: " << outputCornerFile_ << "\n";
}
else if(argument == "-inputTransformFile")
{
argIndex++;
if (argIndex >= argc)
{
throw OdmOrthoPhotoException("Argument '" + argument + "' expects 1 more input following it, but no more inputs were provided.");
}
inputTransformFile_ = std::string(argv[argIndex]);
transformOverride_ = true;
log_ << "Reading transformation matrix from: " << outputCornerFile_ << "\n";
}
else
{
printHelp();
@ -291,9 +181,6 @@ void OdmOrthoPhoto::printHelp()
log_ << "\"-inputFiles <path>[,<path2>,<path3>,...]\" (mandatory)\n";
log_ << "\"Input obj files that must contain a textured mesh.\n\n";
log_ << "\"-inputGeoRefFile <path>\" (optional, if specified boundary points are assumed to be given as world coordinates. If not specified, the boundary points are assumed to be local coordinates)\n";
log_ << "\"Input geograpical reference system file that describes the world position of the model's origin.\n\n";
log_ << "\"-outputFile <path>\" (optional, default: ortho.jpg)\n";
log_ << "\"Target file in which the orthophoto is saved.\n\n";
@ -303,12 +190,6 @@ void OdmOrthoPhoto::printHelp()
log_ << "\"-resolution <pixels/m>\" (mandatory)\n";
log_ << "\"The number of pixels used per meter.\n\n";
log_ << "\"-boundary <Point1x Point1y Point2x Point2y Point3x Point3y Point4x Point4y>\" (optional, if not specified the entire model will be rendered)\n";
log_ << "\"Describes the area which should be covered in the ortho photo. The area will be a bounding box containing all four points. The points should be given in the same georeference system as the model.\n\n";
log_ << "\"-boundaryMinMax <MinX MinY MaxX MaxY>\" (optional, if not specified the entire model will be rendered.)\n";
log_ << "\"Describes the area which should be covered in the ortho photo. The area will be a bounding box with corners at MinX, MinY and MaxX, MaxY. The points should be given in the same georeference system as the model.\n\n";
log_.setIsPrintingInCout(false);
}
@ -357,11 +238,11 @@ inline T maxRange(){
}
template <typename T>
void OdmOrthoPhoto::initBands(const cv::Mat &texture){
void OdmOrthoPhoto::initBands(int count){
size_t pixelCount = static_cast<size_t>(width * height);
// Channels
for (int i = 0; i < texture.channels(); i++){
for (int i = 0; i < count; i++){
T *arr = new T[pixelCount];
for (size_t j = 0; j < pixelCount; j++){
arr[j] = maxRange<T>();
@ -371,7 +252,7 @@ void OdmOrthoPhoto::initBands(const cv::Mat &texture){
}
template <typename T>
void OdmOrthoPhoto::initAlphaBand(const cv::Mat &texture){
void OdmOrthoPhoto::initAlphaBand(){
size_t pixelCount = static_cast<size_t>(width * height);
// Alpha
if (alphaBand == nullptr){
@ -391,35 +272,16 @@ void OdmOrthoPhoto::createOrthoPhoto()
throw OdmOrthoPhotoException("Failed to create ortho photo, no texture meshes given.");
}
if(boundaryDefined_)
{
if(inputGeoRefFile_.empty())
{
// Points are assumed to be given in as local points.
adjustBoundsForLocal();
}
else
{
// Points are assumed to be given in as world points.
adjustBoundsForGeoRef();
}
}
else if(!inputGeoRefFile_.empty())
{
// No boundary points specified, but georeference system file was given.
log_ << "Warning:\n";
log_ << "\tSpecified -inputGeoRefFile, but no boundary points. The georeference system will be ignored.\n";
}
int textureDepth = -1;
float xMax, xMin, yMax, yMin;
bool primary = true;
for (auto &inputFile : inputFiles){
log_ << "Reading mesh file... " << inputFile << "\n";
// The textured mesh.
pcl::TextureMesh mesh;
loadObjFile(inputFile, mesh);
log_ << ".. mesh file read.\n\n";
log_ << "Mesh file read.\n\n";
// Does the model have more than one material?
bool multiMaterial_ = 1 < mesh.tex_materials.size();
@ -434,11 +296,10 @@ void OdmOrthoPhoto::createOrthoPhoto()
}
}
if(!boundaryDefined_)
{
// Determine boundary from model.
// Set boundaries according to the first model
// subsequent models use the boundaries of the first
if (primary){
adjustBoundsForEntireModel(mesh);
boundaryDefined_ = true;
}
// The minimum and maximum boundary values.
@ -458,6 +319,7 @@ void OdmOrthoPhoto::createOrthoPhoto()
// The resolution necessary to fit the area with the given resolution.
height = static_cast<int>(std::ceil(resolution_*yDiff));
width = static_cast<int>(std::ceil(resolution_*xDiff));
depth_ = cv::Mat::zeros(height, width, CV_32F) - std::numeric_limits<float>::infinity();
log_ << "Ortho photo resolution, width x height : " << width << "x" << height << '\n';
// Check size of photo.
@ -550,7 +412,6 @@ void OdmOrthoPhoto::createOrthoPhoto()
{
uvs.insert(uvs.end(), mesh.tex_coordinates[t].begin(), mesh.tex_coordinates[t].end());
}
//cv::namedWindow("dsfs");
// The current material texture
cv::Mat texture;
@ -569,41 +430,24 @@ void OdmOrthoPhoto::createOrthoPhoto()
// The first material determines the bit depth
// Init ortho photo
if (textureDepth == -1){
try{
textureDepth = texture.depth();
log_ << "Texture channels: " << texture.channels() << "\n";
if (t == 0){
if (primary) textureDepth = texture.depth();
else if (textureDepth != texture.depth()) throw OdmOrthoPhotoException("Texture depth must be the same for all models");
if (textureDepth == CV_8U){
log_ << "Texture depth: 8bit\n";
initBands<uint8_t>(texture);
initAlphaBand<uint8_t>(texture);
}else if (textureDepth == CV_16U){
log_ << "Texture depth: 16bit\n";
initBands<uint16_t>(texture);
initAlphaBand<uint16_t>(texture);
}else{
std::cerr << "Unsupported bit depth value: " << textureDepth;
exit(1);
}
depth_ = cv::Mat::zeros(height, width, CV_32F) - std::numeric_limits<float>::infinity();
}catch(const std::bad_alloc &){
std::cerr << "Couldn't allocate enough memory to render the orthophoto (" << width << "x" << height << " cells = " << ((long long)width * (long long)height * 4) << " bytes). Try to increase the --orthophoto-resolution parameter to a larger integer or add more RAM.\n";
exit(1);
}
}else{
// Quick checks
if (textureDepth != texture.depth()) throw OdmOrthoPhotoException("Texture depth must be the same for all models");
log_ << "Texture channels: " << texture.channels() << "\n";
try{
if (textureDepth == CV_8U){
log_ << "Texture depth: 8bit\n";
initBands<uint8_t>(texture);
initBands<uint8_t>(texture.channels());
if (primary) initAlphaBand<uint8_t>();
}else if (textureDepth == CV_16U){
log_ << "Texture depth: 16bit\n";
initBands<uint16_t>(texture);
initBands<uint16_t>(texture.channels());
if (primary) initAlphaBand<uint16_t>();
}else{
std::cerr << "Unsupported bit depth value: " << textureDepth;
exit(1);
}
}catch(const std::bad_alloc &){
std::cerr << "Couldn't allocate enough memory to render the orthophoto (" << width << "x" << height << " cells = " << ((long long)width * (long long)height * 4) << " bytes). Try to increase the --orthophoto-resolution parameter to a larger integer or add more RAM.\n";
@ -639,9 +483,10 @@ void OdmOrthoPhoto::createOrthoPhoto()
faceOff += faces.size();
log_ << "Material " << t << " rendered.\n";
}
log_ << "...ortho photo rendered\n";
log_ << "... model rendered\n";
currentBandIndex += texture.channels();
primary = false;
}
log_ << '\n';
@ -673,73 +518,6 @@ void OdmOrthoPhoto::createOrthoPhoto()
log_ << "Orthophoto generation done.\n";
}
void OdmOrthoPhoto::adjustBoundsForGeoRef()
{
log_ << "Adjusting bounds for world coordinates\n";
// A stream of the georef system.
std::ifstream geoRefStream(inputGeoRefFile_.c_str());
// The system name
std::string system;
// The east and north offsets
int eastOffset, northOffset;
// Parse file
std::getline(geoRefStream, system);
if(!(geoRefStream >> eastOffset))
{
throw OdmOrthoPhotoException("Could not extract geographical reference system from \n" + inputGeoRefFile_ + "\nCould not extract east offset.");
}
if(!(geoRefStream >> northOffset))
{
throw OdmOrthoPhotoException("Could not extract geographical reference system from \n" + inputGeoRefFile_ + "\nCould not extract north offset.");
}
log_ << "Georeference system:\n";
log_ << system << "\n";
log_ << "East offset: " << eastOffset << "\n";
log_ << "North offset: " << northOffset << "\n";
// Adjust boundary points.
boundaryPoint1_[0] = static_cast<float>(worldPoint1_.eastInteger_ - eastOffset) + worldPoint1_.eastFractional_;
boundaryPoint1_[1] = static_cast<float>(worldPoint1_.northInteger_ - northOffset) + worldPoint1_.northFractional_;
boundaryPoint2_[0] = static_cast<float>(worldPoint2_.eastInteger_ - eastOffset) + worldPoint2_.eastFractional_;
boundaryPoint2_[1] = static_cast<float>(worldPoint2_.northInteger_ - northOffset) + worldPoint2_.northFractional_;
boundaryPoint3_[0] = static_cast<float>(worldPoint3_.eastInteger_ - eastOffset) + worldPoint3_.eastFractional_;
boundaryPoint3_[1] = static_cast<float>(worldPoint3_.northInteger_ - northOffset) + worldPoint3_.northFractional_;
boundaryPoint4_[0] = static_cast<float>(worldPoint4_.eastInteger_ - eastOffset) + worldPoint4_.eastFractional_;
boundaryPoint4_[1] = static_cast<float>(worldPoint4_.northInteger_ - northOffset) + worldPoint4_.northFractional_;
log_ << "Local boundary points:\n";
log_ << "Point 1: " << boundaryPoint1_[0] << " " << boundaryPoint1_[1] << "\n";
log_ << "Point 2: " << boundaryPoint2_[0] << " " << boundaryPoint2_[1] << "\n";
log_ << "Point 3: " << boundaryPoint3_[0] << " " << boundaryPoint3_[1] << "\n";
log_ << "Point 4: " << boundaryPoint4_[0] << " " << boundaryPoint4_[1] << "\n";
}
void OdmOrthoPhoto::adjustBoundsForLocal()
{
log_ << "Adjusting bounds for local coordinates\n";
// Set boundary points from world points.
boundaryPoint1_[0] = static_cast<float>(worldPoint1_.eastInteger_ ) + worldPoint1_.eastFractional_;
boundaryPoint1_[1] = static_cast<float>(worldPoint1_.northInteger_) + worldPoint1_.northFractional_;
boundaryPoint2_[0] = static_cast<float>(worldPoint2_.eastInteger_ ) + worldPoint2_.eastFractional_;
boundaryPoint2_[1] = static_cast<float>(worldPoint2_.northInteger_) + worldPoint2_.northFractional_;
boundaryPoint3_[0] = static_cast<float>(worldPoint3_.eastInteger_ ) + worldPoint3_.eastFractional_;
boundaryPoint3_[1] = static_cast<float>(worldPoint3_.northInteger_) + worldPoint3_.northFractional_;
boundaryPoint4_[0] = static_cast<float>(worldPoint4_.eastInteger_ ) + worldPoint4_.eastFractional_;
boundaryPoint4_[1] = static_cast<float>(worldPoint4_.northInteger_) + worldPoint4_.northFractional_;
log_ << "Local boundary points:\n";
log_ << "Point 1: " << boundaryPoint1_[0] << " " << boundaryPoint1_[1] << "\n";
log_ << "Point 2: " << boundaryPoint2_[0] << " " << boundaryPoint2_[1] << "\n";
log_ << "Point 3: " << boundaryPoint3_[0] << " " << boundaryPoint3_[1] << "\n";
log_ << "Point 4: " << boundaryPoint4_[0] << " " << boundaryPoint4_[1] << "\n";
log_ << "\n";
}
void OdmOrthoPhoto::adjustBoundsForEntireModel(const pcl::TextureMesh &mesh)
{
log_ << "Set boundary to contain entire model.\n";
@ -800,70 +578,28 @@ void OdmOrthoPhoto::adjustBoundsForEntireModel(const pcl::TextureMesh &mesh)
Eigen::Transform<float, 3, Eigen::Affine> OdmOrthoPhoto::getROITransform(float xMin, float yMin) const
{
//Use transformation matrix if provided:
if(transformOverride_){
return readTransform(inputTransformFile_);
}
else {
// The transform used to move the chosen area into the ortho photo.
Eigen::Transform<float, 3, Eigen::Affine> transform;
transform(0, 0) = resolution_; // x Scaling.
transform(1, 0) = 0.0f;
transform(2, 0) = 0.0f;
transform(3, 0) = 0.0f;
transform(0, 1) = 0.0f;
transform(1, 1) = -resolution_; // y Scaling, mirrored for easier rendering.
transform(2, 1) = 0.0f;
transform(3, 1) = 0.0f;
transform(0, 2) = 0.0f;
transform(1, 2) = 0.0f;
transform(2, 2) = 1.0f;
transform(3, 2) = 0.0f;
transform(0, 3) = -xMin * resolution_; // x Translation
transform(1, 3) = -yMin * resolution_; // y Translation
transform(2, 3) = 0.0f;
transform(3, 3) = 1.0f;
return transform;
}
}
Eigen::Transform<float, 3, Eigen::Affine> OdmOrthoPhoto::readTransform(std::string transformFile_) const
{
// The transform used to move the chosen area into the ortho photo.
Eigen::Transform<float, 3, Eigen::Affine> transform;
std::ifstream transStream(transformFile_.c_str());
if (!transStream.good())
{
throw OdmOrthoPhotoException("Failed opening coordinate file " + transformFile_ + " for reading. " + '\n');
}
transform(0, 0) = resolution_; // x Scaling.
transform(1, 0) = 0.0f;
transform(2, 0) = 0.0f;
transform(3, 0) = 0.0f;
std::string transString;
{
std::getline(transStream, transString);
std::stringstream l1(transString);
l1 >> transform(0,0) >> transform(0,1) >> transform(0,2) >> transform(0,3);
transform(0, 1) = 0.0f;
transform(1, 1) = -resolution_; // y Scaling, mirrored for easier rendering.
transform(2, 1) = 0.0f;
transform(3, 1) = 0.0f;
std::getline(transStream, transString);
std::stringstream l2(transString);
l2 >> transform(1,0) >> transform(1,1) >> transform(1,2) >> transform(1,3);
transform(0, 2) = 0.0f;
transform(1, 2) = 0.0f;
transform(2, 2) = 1.0f;
transform(3, 2) = 0.0f;
std::getline(transStream, transString);
std::stringstream l3(transString);
l3 >> transform(2,0) >> transform(2,1) >> transform(2,2) >> transform(2,3);
std::getline(transStream, transString);
std::stringstream l4(transString);
l4 >> transform(3,0) >> transform(3,1) >> transform(3,2) >> transform(3,3);
}
// Don't do any rotation/shear
transform(0,1) = 0.0f;
transform(1,0) = 0.0f;
transform(0, 3) = -xMin * resolution_; // x Translation
transform(1, 3) = -yMin * resolution_; // y Translation
transform(2, 3) = 0.0f;
transform(3, 3) = 1.0f;
return transform;
}
@ -1155,14 +891,16 @@ void OdmOrthoPhoto::renderPixel(int row, int col, float s, float t, const cv::Ma
// The interpolated color values.
size_t idx = static_cast<size_t>(row * width + col);
T *data = reinterpret_cast<T *>(texture.data); // Faster access
int numChannels = texture.channels();
for (int i = 0; i < texture.channels(); i++){
for (int i = 0; i < numChannels; i++){
float value = 0.0f;
T tl = texture.at<T>(top, left, i);
T tr = texture.at<T>(top, left+1, i);
T bl = texture.at<T>(top+1, left, i);
T br = texture.at<T>(top+1, left+1, i);
T tl = data[(top) * texture.cols * numChannels + (left) * numChannels + i];
T tr = data[(top) * texture.cols * numChannels + (left + 1) * numChannels + i];
T bl = data[(top + 1) * texture.cols * numChannels + (left) * numChannels + i];
T br = data[(top + 1) * texture.cols * numChannels + (left + 1) * numChannels + i];
value += static_cast<float>(tl) * dr * db;
value += static_cast<float>(tr) * dl * db;

Wyświetl plik

@ -27,36 +27,6 @@
// Logger
#include "Logger.hpp"
/*!
* \brief The WorldPoint struct encapsules world coordinates used for the ortho photo boundary.
* Points are separated into integers and fractional parts for high numerical stability.
*/
struct WorldPoint
{
int eastInteger_; /**< The inger part of the east point. */
float eastFractional_; /**< The farctional part of the east point. */
int northInteger_; /**< The inger part of the east point. */
float northFractional_; /**< The farctional part of the east point. */
/*!
* \brief Overloads operator '<<' for WorldPoint.
*
* \param os The output stream in which the WorldPoint should be printed.
* \param worldPoint The WorldPoint should be printed.
* \return A reference to the given output stream.
*/
friend std::ostream & operator<< (std::ostream &os, const WorldPoint &worldPoint);
/*!
* \brief Overloads operator '>>' for WorldPoint.
*
* \param is The input stream from which the WorldPoint should be extracted
* \param worldPoint The modified WorldPoint.
* \return A reference to the given input stream.
*/
friend std::istream & operator>> (std::istream &os, WorldPoint &worldPoint);
};
/*!
* \brief The OdmOrthoPhoto class is used to create an orthographic photo over a given area.
* The class reads an oriented textured mesh from an OBJ-file.
@ -82,34 +52,11 @@ public:
private:
int width, height;
/*!
* \brief parseArguments Parses command line arguments.
*
* \param argc Application argument count.
* \param argv Argument values.
*/
void parseArguments(int argc, char* argv[]);
/*!
* \brief printHelp Prints help, explaining usage. Can be shown by calling the program with argument: "-help".
*/
void printHelp();
/*!
* \brief Create the ortho photo using the current settings.
*/
void createOrthoPhoto();
/*!
* \brief Adjusts the boundary points according to the given georef system.
*/
void adjustBoundsForGeoRef();
/*!
* \brief Adjusts the boundary points assuming the wolrd points are relative the local coordinate system.
*/
void adjustBoundsForLocal();
/*!
* \brief Adjusts the boundary points so that the entire model fits inside the photo.
*
@ -122,18 +69,11 @@ private:
*/
Eigen::Transform<float, 3, Eigen::Affine> getROITransform(float xMin, float yMin) const;
/*!
* \brief Reads a transformation matrix from a file
* @param transformFile_
* @return
*/
Eigen::Transform<float, 3, Eigen::Affine> readTransform(std::string transformFile_) const;
template <typename T>
void initBands(int count);
template <typename T>
void initBands(const cv::Mat &texture);
template <typename T>
void initAlphaBand(const cv::Mat &texture);
void initAlphaBand();
void saveTIFF(const std::string &filename, GDALDataType dataType);
@ -214,22 +154,12 @@ private:
Logger log_; /**< Logging object. */
std::vector<std::string> inputFiles;
std::string inputGeoRefFile_; /**< Path to the georeference system file. */
std::string inputTransformFile_;
std::string outputFile_; /**< Path to the destination file. */
std::string outputCornerFile_; /**< Path to the output corner file. */
std::string logFile_; /**< Path to the log file. */
float resolution_; /**< The number of pixels per meter in the ortho photo. */
bool transformOverride_;
bool boundaryDefined_; /**< True if the user has defined a boundary. */
WorldPoint worldPoint1_; /**< The first boundary point for the ortho photo, in world coordinates. */
WorldPoint worldPoint2_; /**< The second boundary point for the ortho photo, in world coordinates. */
WorldPoint worldPoint3_; /**< The third boundary point for the ortho photo, in world coordinates. */
WorldPoint worldPoint4_; /**< The fourth boundary point for the ortho photo, in world coordinates. */
Eigen::Vector2f boundaryPoint1_; /**< The first boundary point for the ortho photo, in local coordinates. */
Eigen::Vector2f boundaryPoint2_; /**< The second boundary point for the ortho photo, in local coordinates. */
Eigen::Vector2f boundaryPoint3_; /**< The third boundary point for the ortho photo, in local coordinates. */