OpenDroneMap-ODM/modules/odm_orthophoto/src/OdmOrthoPhoto.hpp

258 wiersze
9.6 KiB
C++

#pragma once
// C++
#include <limits.h>
#include <istream>
#include <ostream>
// PCL
#include <pcl/io/obj_io.h>
#include <pcl/common/transforms.h>
// OpenCV
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
// PCL
#include <pcl/common/eigen.h>
#include <pcl/common/common.h>
// OpenCV
#include <opencv2/core/core.hpp>
// GDAL
#include "gdal_priv.h"
#include "cpl_conv.h" // for CPLMalloc()
// 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.
* The class uses file read from pcl.
* The class uses image read and write from opencv.
*/
class OdmOrthoPhoto
{
public:
OdmOrthoPhoto();
~OdmOrthoPhoto();
/*!
* \brief run Runs the ortho photo functionality using the provided input arguments.
* For a list of accepted arguments, pleas see the main page documentation or
* call the program with parameter "-help".
* \param argc Application argument count.
* \param argv Argument values.
* \return 0 if successful.
*/
int run(int argc, char* argv[]);
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.
*
* \param mesh The model which decides the boundary.
*/
void adjustBoundsForEntireModel(const pcl::TextureMesh &mesh);
/*!
* \brief Creates a transformation which aligns the area for the orthophoto.
*/
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(const cv::Mat &texture);
void saveTIFF(const std::string &filename, GDALDataType dataType);
/*!
* \brief Renders a triangle into the ortho photo.
*
* Pixel center defined as middle of pixel for triangle rasterisation, and in lower left corner for texture look-up.
*
* \param texture The texture of the polygon.
* \param polygon The polygon as athree indices relative meshCloud.
* \param meshCloud Contains all vertices.
* \param uvs Contains the texture coordinates for the active material.
* \param faceIndex The index of the face.
*/
template <typename T>
void drawTexturedTriangle(const cv::Mat &texture, const pcl::Vertices &polygon, const pcl::PointCloud<pcl::PointXYZ>::Ptr &meshCloud, const std::vector<Eigen::Vector2f> &uvs, size_t faceIndex);
/*!
* \brief Sets the color of a pixel in the photo.
*
* \param row The row index of the pixel.
* \param col The column index of the pixel.
* \param s The u texture-coordinate, multiplied with the number of columns in the texture.
* \param t The v texture-coordinate, multiplied with the number of rows in the texture.
* \param texture The texture from which to get the color.
**/
template <typename T>
void renderPixel(int row, int col, float u, float v, const cv::Mat &texture);
/*!
* \brief Calculates the barycentric coordinates of a point in a triangle.
*
* \param v1 The first triangle vertex.
* \param v2 The second triangle vertex.
* \param v3 The third triangle vertex.
* \param x The x coordinate of the point.
* \param y The y coordinate of the point.
* \param l1 The first vertex weight.
* \param l2 The second vertex weight.
* \param l3 The third vertex weight.
*/
void getBarycentricCoordinates(pcl::PointXYZ v1, pcl::PointXYZ v2, pcl::PointXYZ v3, float x, float y, float &l1, float &l2, float &l3) const;
/*!
* \brief Check if a given polygon is a sliver polygon.
*
* \param v1 The first vertex of the polygon.
* \param v2 The second vertex of the polygon.
* \param v3 The third vertex of the polygon.
*/
bool isSliverPolygon(pcl::PointXYZ v1, pcl::PointXYZ v2, pcl::PointXYZ v3) const;
/*!
* \brief Check if the model is suitable for ortho photo generation.
*
* \param mesh The model.
* \return True if the model is ok for generating ortho photo.
*/
bool isModelOk(const pcl::TextureMesh &mesh);
/*!
* \brief Loads a model from an .obj file (replacement for the pcl obj loader).
*
* \param inputFile Path to the .obj file.
* \param mesh The model.
* \return True if model was loaded successfully.
*/
bool loadObjFile(std::string inputFile, pcl::TextureMesh &mesh);
/*!
* \brief Function is compied straight from the function in the pcl::io module.
*/
bool readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
int &file_version, int &data_type, unsigned int &data_idx,
const int offset);
Logger log_; /**< Logging object. */
std::string inputFile_; /**< Path to the textured mesh as an obj-file. */
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. */
Eigen::Vector2f boundaryPoint4_; /**< The fourth boundary point for the ortho photo, in local coordinates. */
std::vector<void *> bands;
cv::Mat depth_; /**< The depth of the ortho photo as an OpenCV matrix, CV_32F. */
bool multiMaterial_; /**< True if the mesh has multiple materials. **/
std::vector<pcl::MTLReader> companions_; /**< Materials (used by loadOBJFile). **/
};
/*!
* \brief The OdmOrthoPhoto class
*/
class OdmOrthoPhotoException : public std::exception
{
public:
OdmOrthoPhotoException() : message("Error in OdmOrthoPhoto") {}
OdmOrthoPhotoException(std::string msgInit) : message("Error in OdmOrthoPhoto:\n" + msgInit) {}
~OdmOrthoPhotoException() throw() {}
virtual const char* what() const throw() {return message.c_str(); }
private:
std::string message; /**< The error message **/
};