kopia lustrzana https://github.com/OpenDroneMap/ODM
Removed utm_extractor module, exiv2 deps, reformat core2.Dockerfile
Former-commit-id: 9747197c4b
pull/1161/head
rodzic
779d48d272
commit
e094b79533
|
@ -130,7 +130,6 @@ RUN rm -rf \
|
|||
/code/SuperBuild/build/opencv \
|
||||
/code/SuperBuild/download \
|
||||
/code/SuperBuild/src/ceres \
|
||||
/code/SuperBuild/src/exiv2lib \
|
||||
/code/SuperBuild/src/mvstexturing \
|
||||
/code/SuperBuild/src/opencv \
|
||||
/code/SuperBuild/src/opengv \
|
||||
|
|
|
@ -112,7 +112,6 @@ set(custom_libs OpenGV
|
|||
Catkin
|
||||
Ecto
|
||||
LASzip
|
||||
Exiv2
|
||||
PDAL
|
||||
MvsTexturing
|
||||
)
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
set(_proj_name exiv2lib)
|
||||
set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}")
|
||||
|
||||
ExternalProject_Add(${_proj_name}
|
||||
PREFIX ${_SB_BINARY_DIR}
|
||||
TMP_DIR ${_SB_BINARY_DIR}/tmp
|
||||
STAMP_DIR ${_SB_BINARY_DIR}/stamp
|
||||
DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name}
|
||||
URL https://github.com/Exiv2/exiv2/archive/0.27.tar.gz
|
||||
SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=${SB_INSTALL_DIR}
|
||||
-DCMAKE_INSTALL_LIBDIR=lib
|
||||
BUILD_IN_SOURCE ON
|
||||
BUILD_COMMAND make exiv2lib
|
||||
INSTALL_DIR ${SB_INSTALL_DIR}
|
||||
LOG_DOWNLOAD OFF
|
||||
LOG_CONFIGURE OFF
|
||||
LOG_BUILD OFF
|
||||
)
|
117
core2.Dockerfile
117
core2.Dockerfile
|
@ -3,30 +3,87 @@ FROM phusion/baseimage
|
|||
# Env variables
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
#Install dependencies
|
||||
#Required Requisites
|
||||
RUN add-apt-repository -y ppa:ubuntugis/ppa
|
||||
RUN add-apt-repository -y ppa:george-edison55/cmake-3.x
|
||||
RUN apt-get update -y
|
||||
#Install dependencies and required requisites
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y \
|
||||
software-properties-common \
|
||||
&& add-apt-repository -y ppa:ubuntugis/ppa \
|
||||
&& add-apt-repository -y ppa:george-edison55/cmake-3.x \
|
||||
&& apt-get update -y
|
||||
|
||||
# All packages (Will install much faster)
|
||||
RUN apt-get install --no-install-recommends -y git cmake python-pip build-essential software-properties-common python-software-properties libgdal-dev gdal-bin libgeotiff-dev \
|
||||
libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libflann-dev \
|
||||
libproj-dev libxext-dev liblapack-dev libeigen3-dev libvtk6-dev python-networkx libgoogle-glog-dev libsuitesparse-dev libboost-filesystem-dev libboost-iostreams-dev \
|
||||
libboost-regex-dev libboost-python-dev libboost-date-time-dev libboost-thread-dev python-pyproj python-empy python-nose python-pyside \
|
||||
liblas-bin python-matplotlib libatlas-base-dev swig2.0 python-wheel libboost-log-dev libjsoncpp-dev python-gdal
|
||||
RUN apt-get install --no-install-recommends -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
gdal-bin \
|
||||
git \
|
||||
libatlas-base-dev \
|
||||
libavcodec-dev \
|
||||
libavformat-dev \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-log-dev \
|
||||
libboost-python-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-thread-dev \
|
||||
libeigen3-dev \
|
||||
libflann-dev \
|
||||
libgdal-dev \
|
||||
libgeotiff-dev \
|
||||
libgoogle-glog-dev \
|
||||
libgtk2.0-dev \
|
||||
libjasper-dev \
|
||||
libjpeg-dev \
|
||||
libjsoncpp-dev \
|
||||
liblapack-dev \
|
||||
liblas-bin \
|
||||
libpng-dev \
|
||||
libproj-dev \
|
||||
libsuitesparse-dev \
|
||||
libswscale-dev \
|
||||
libtbb2 \
|
||||
libtbb-dev \
|
||||
libtiff-dev \
|
||||
libvtk6-dev \
|
||||
libxext-dev \
|
||||
python-dev \
|
||||
python-empy \
|
||||
python-gdal \
|
||||
python-matplotlib \
|
||||
python-networkx \
|
||||
python-nose \
|
||||
python-pip \
|
||||
python-pyproj \
|
||||
python-pyside \
|
||||
python-software-properties \
|
||||
python-wheel \
|
||||
swig2.0
|
||||
|
||||
RUN apt-get remove libdc1394-22-dev
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install setuptools
|
||||
RUN pip install -U PyYAML exifread gpxpy xmltodict catkin-pkg appsettings https://github.com/OpenDroneMap/gippy/archive/numpyfix.zip loky shapely scipy numpy==1.15.4 pyproj psutil repoze.lru
|
||||
RUN pip install -U \
|
||||
appsettings \
|
||||
catkin-pkg \
|
||||
exifread \
|
||||
gpxpy \
|
||||
loky \
|
||||
numpy==1.15.4 \
|
||||
psutil \
|
||||
pyproj \
|
||||
PyYAML \
|
||||
repoze.lru \
|
||||
scipy \
|
||||
shapely \
|
||||
xmltodict \
|
||||
https://github.com/OpenDroneMap/gippy/archive/numpyfix.zip
|
||||
|
||||
ENV PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python2.7/dist-packages"
|
||||
ENV PYTHONPATH="$PYTHONPATH:/code/SuperBuild/src/opensfm"
|
||||
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib"
|
||||
|
||||
# Prepare directories
|
||||
|
||||
RUN mkdir /code
|
||||
WORKDIR /code
|
||||
|
||||
|
@ -46,21 +103,45 @@ COPY VERSION /code/VERSION
|
|||
|
||||
# Replace g++ and gcc with our own scripts
|
||||
COPY /docker/ /code/docker/
|
||||
RUN mv -v /usr/bin/gcc /usr/bin/gcc_real && mv -v /usr/bin/g++ /usr/bin/g++_real && cp -v /code/docker/gcc /usr/bin/gcc && cp -v /code/docker/g++ /usr/bin/g++
|
||||
RUN mv -v /usr/bin/gcc /usr/bin/gcc_real \
|
||||
&& mv -v /usr/bin/g++ /usr/bin/g++_real \
|
||||
&& cp -v /code/docker/gcc /usr/bin/gcc \
|
||||
&& cp -v /code/docker/g++ /usr/bin/g++
|
||||
|
||||
#Compile code in SuperBuild and root directories
|
||||
# Compile code in SuperBuild and root directories
|
||||
RUN cd SuperBuild \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake .. \
|
||||
&& make -j$(nproc) \
|
||||
&& cd ../.. \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake .. \
|
||||
&& make -j$(nproc)
|
||||
|
||||
RUN cd SuperBuild && mkdir build && cd build && cmake .. && make -j$(nproc) && cd ../.. && mkdir build && cd build && cmake .. && make -j$(nproc)
|
||||
RUN apt-get -y remove \
|
||||
git \
|
||||
build-essential \
|
||||
cmake \
|
||||
libgl1-mesa-dri \
|
||||
python-pip
|
||||
|
||||
RUN apt-get -y remove libgl1-mesa-dri git cmake python-pip build-essential
|
||||
RUN apt-get install -y libvtk6-dev
|
||||
|
||||
# Cleanup APT
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Clean Superbuild
|
||||
|
||||
RUN rm -rf /code/SuperBuild/download /code/SuperBuild/src/opencv /code/SuperBuild/src/pcl /code/SuperBuild/src/pdal /code/SuperBuild/src/opengv /code/SuperBuild/src/mvstexturing /code/SuperBuild/src/ceres /code/SuperBuild/build/opencv /code/SuperBuild/src/exiv2lib
|
||||
RUN rm -rf \
|
||||
/code/SuperBuild/build/opencv \
|
||||
/code/SuperBuild/download \
|
||||
/code/SuperBuild/src/ceres \
|
||||
/code/SuperBuild/src/mvstexturing \
|
||||
/code/SuperBuild/src/opencv \
|
||||
/code/SuperBuild/src/opengv \
|
||||
/code/SuperBuild/src/pcl \
|
||||
/code/SuperBuild/src/pdal
|
||||
|
||||
# Entry point
|
||||
ENTRYPOINT ["python", "/code/run.py", "code"]
|
||||
|
|
|
@ -4,7 +4,6 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||
endif()
|
||||
|
||||
# Add ODM sub-modules
|
||||
add_subdirectory(odm_extract_utm)
|
||||
add_subdirectory(odm_georef)
|
||||
add_subdirectory(odm_orthophoto)
|
||||
add_subdirectory(odm_cleanmesh)
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
project(odm_extract_utm)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(PROJ4_INCLUDE_DIR "/usr/include/" CACHE "PROJ4_INCLUDE_DIR" "Path to the proj4 inlcude directory")
|
||||
|
||||
find_library(PROJ4_LIBRARY "libproj.so" PATHS "/usr/lib" "/usr/lib/x86_64-linux-gnu")
|
||||
find_library(EXIV2_LIBRARY "libexiv2.so.27" PATHS "${PROJECT_SOURCE_DIR}/../../SuperBuild/install/lib")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/../../SuperBuild/install/include")
|
||||
|
||||
# Add compiler options.
|
||||
add_definitions(-Wall -Wextra)
|
||||
|
||||
# Add source directory
|
||||
aux_source_directory("./src" SRC_LIST)
|
||||
|
||||
# Add exectuteable
|
||||
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||
|
||||
# Link
|
||||
target_link_libraries(${PROJECT_NAME} ${PROJ4_LIBRARY} ${EXIV2_LIBRARY})
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#include "Logger.hpp"
|
||||
|
||||
|
||||
Logger::Logger(bool isPrintingInCout) : isPrintingInCout_(isPrintingInCout)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Logger::printToFile(std::string filePath)
|
||||
{
|
||||
std::ofstream file(filePath.c_str(), std::ios::binary);
|
||||
file << logStream_.str();
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool Logger::isPrintingInCout() const
|
||||
{
|
||||
return isPrintingInCout_;
|
||||
}
|
||||
|
||||
void Logger::setIsPrintingInCout(bool isPrintingInCout)
|
||||
{
|
||||
isPrintingInCout_ = isPrintingInCout;
|
||||
}
|
||||
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
/*!
|
||||
* \brief The Logger class is used to store program messages in a log file.
|
||||
* \details By using the << operator while printInCout is set, the class writes both to
|
||||
* cout and to file, if the flag is not set, output is written to file only.
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Logger Contains functionality for printing and displaying log information.
|
||||
* \param printInCout Flag toggling if operator << also writes to cout.
|
||||
*/
|
||||
Logger(bool isPrintingInCout = true);
|
||||
|
||||
/*!
|
||||
* \brief Destructor.
|
||||
*/
|
||||
~Logger();
|
||||
|
||||
/*!
|
||||
* \brief print Prints the contents of the log to file.
|
||||
* \param filePath Path specifying where to write the log.
|
||||
*/
|
||||
void printToFile(std::string filePath);
|
||||
|
||||
/*!
|
||||
* \brief isPrintingInCout Check if console printing flag is set.
|
||||
* \return Console printing flag.
|
||||
*/
|
||||
bool isPrintingInCout() const;
|
||||
|
||||
/*!
|
||||
* \brief setIsPrintingInCout Set console printing flag.
|
||||
* \param isPrintingInCout Value, if true, messages added to the log are also printed in cout.
|
||||
*/
|
||||
void setIsPrintingInCout(bool isPrintingInCout);
|
||||
|
||||
/*!
|
||||
* Operator for printing messages to log and in the standard output stream if desired.
|
||||
*/
|
||||
template<class T>
|
||||
friend Logger& operator<< (Logger &log, T t)
|
||||
{
|
||||
// If console printing is enabled.
|
||||
if (log.isPrintingInCout_)
|
||||
{
|
||||
std::cout << t;
|
||||
std::cout.flush();
|
||||
}
|
||||
// Write to log.
|
||||
log.logStream_ << t;
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
private:
|
||||
bool isPrintingInCout_; /*!< If flag is set, log is printed in cout and written to the log. */
|
||||
|
||||
std::stringstream logStream_; /*!< Stream for storing the log. */
|
||||
};
|
|
@ -1,353 +0,0 @@
|
|||
// STL
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
#include <exiv2/exiv2.hpp>
|
||||
|
||||
// Proj4
|
||||
#include <proj_api.h>
|
||||
|
||||
// This
|
||||
#include "UtmExtractor.hpp"
|
||||
|
||||
UtmExtractor::UtmExtractor() : log_(false)
|
||||
{
|
||||
logFile_ = "odm_extracting_utm_log.txt";
|
||||
}
|
||||
|
||||
UtmExtractor::~UtmExtractor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
int UtmExtractor::run(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 1)
|
||||
{
|
||||
printHelp();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
parseArguments(argc, argv);
|
||||
extractUtm();
|
||||
}
|
||||
catch (const UtmExtractorException& e)
|
||||
{
|
||||
log_.setIsPrintingInCout(true);
|
||||
log_ << e.what() << "\n";
|
||||
log_.printToFile(logFile_);
|
||||
log_ << "For more detailed information, see log file." << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
log_.setIsPrintingInCout(true);
|
||||
log_ << "Error in OdmExtractUtm:\n";
|
||||
log_ << e.what() << "\n";
|
||||
log_.printToFile(logFile_);
|
||||
log_ << "For more detailed information, see log file." << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log_.setIsPrintingInCout(true);
|
||||
log_ << "Unknown error in OdmExtractUtm:\n";
|
||||
log_.printToFile(logFile_);
|
||||
log_ << "For more detailed information, see log file." << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
log_.printToFile(logFile_);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void UtmExtractor::parseArguments(int argc, char **argv)
|
||||
{
|
||||
for(int argIndex = 1; argIndex < argc; ++argIndex)
|
||||
{
|
||||
// The argument to be parsed
|
||||
std::string argument = std::string(argv[argIndex]);
|
||||
if (argument == "-help")
|
||||
{
|
||||
printHelp();
|
||||
}
|
||||
else if (argument == "-verbose")
|
||||
{
|
||||
log_.setIsPrintingInCout(true);
|
||||
}
|
||||
else if (argument == "-imageListFile")
|
||||
{
|
||||
++argIndex;
|
||||
if (argIndex >= argc)
|
||||
{
|
||||
throw UtmExtractorException("Missing argument for '" + argument + "'.");
|
||||
}
|
||||
imageListFileName_ = std::string(argv[argIndex]);
|
||||
std::ifstream testFile(imageListFileName_.c_str(), std::ios_base::binary);
|
||||
if (!testFile.is_open())
|
||||
{
|
||||
throw UtmExtractorException("Argument '" + argument + "' has a bad value (file not accessible).");
|
||||
}
|
||||
log_ << "imageListFile was set to: " << imageListFileName_ << "\n";
|
||||
}
|
||||
else if (argument == "-imagesPath")
|
||||
{
|
||||
++argIndex;
|
||||
if (argIndex >= argc)
|
||||
{
|
||||
throw UtmExtractorException("Missing argument for '" + argument + "'.");
|
||||
}
|
||||
std::stringstream ss(argv[argIndex]);
|
||||
ss >> imagesPath_;
|
||||
if (ss.bad())
|
||||
{
|
||||
throw UtmExtractorException("Argument '" + argument + "' has a bad value. (wrong type)");
|
||||
}
|
||||
log_ << "imagesPath was set to: " << imagesPath_ << "\n";
|
||||
}
|
||||
else if (argument == "-outputCoordFile")
|
||||
{
|
||||
++argIndex;
|
||||
if (argIndex >= argc)
|
||||
{
|
||||
throw UtmExtractorException("Missing argument for '" + argument + "'.");
|
||||
}
|
||||
std::stringstream ss(argv[argIndex]);
|
||||
ss >> outputCoordFileName_;
|
||||
if (ss.bad())
|
||||
{
|
||||
throw UtmExtractorException("Argument '" + argument + "' has a bad value. (wrong type)");
|
||||
}
|
||||
log_ << "outputCoordFile was set to: " << outputCoordFileName_ << "\n";
|
||||
}
|
||||
else if (argument == "-logFile")
|
||||
{
|
||||
++argIndex;
|
||||
if (argIndex >= argc)
|
||||
{
|
||||
throw UtmExtractorException("Missing argument for '" + argument + "'.");
|
||||
}
|
||||
std::stringstream ss(argv[argIndex]);
|
||||
ss >> logFile_;
|
||||
if (ss.bad())
|
||||
{
|
||||
throw UtmExtractorException("Argument '" + argument + "' has a bad value. (wrong type)");
|
||||
}
|
||||
log_ << "logFile_ was set to: " << logFile_ << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
printHelp();
|
||||
throw UtmExtractorException("Unrecognised argument '" + argument + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UtmExtractor::extractUtm()
|
||||
{
|
||||
// Open file listing all used camera images
|
||||
std::ifstream imageListStream(imageListFileName_.c_str());
|
||||
if (!imageListStream.good()) {
|
||||
throw UtmExtractorException("Failed to open " + imageListFileName_ + " for reading.");
|
||||
}
|
||||
|
||||
// Traverse images
|
||||
int utmZone = 99; // for auto-select
|
||||
char hemisphere;
|
||||
std::string imageFilename;
|
||||
std::vector<Coord> coords;
|
||||
while (getline(imageListStream, imageFilename)) {
|
||||
|
||||
// Read image and load metadata
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(imagesPath_ + "/" + imageFilename);
|
||||
if (image.get() == 0) {
|
||||
std::string error(imageFilename);
|
||||
error += ": Image cannot be read";
|
||||
throw std::runtime_error(error.c_str());
|
||||
}
|
||||
else {
|
||||
image->readMetadata();
|
||||
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::string error(imageFilename);
|
||||
error += ": No Exif data found in the file";
|
||||
throw std::runtime_error(error.c_str());
|
||||
}
|
||||
|
||||
// Parse exif data for positional data
|
||||
double lon, lat, alt = 0.0;
|
||||
|
||||
parsePosition(exifData, lon, lat, alt);
|
||||
|
||||
if (lon == 0.0 || lat == 0.0 || alt == 0.0) {
|
||||
std::string error("Failed parsing GPS position for " + imageFilename);
|
||||
throw UtmExtractorException(error);
|
||||
}
|
||||
// Convert to UTM
|
||||
double x, y, z = 0.0;
|
||||
convert(lon, lat, alt, x, y, z, utmZone, hemisphere);
|
||||
if (x == 0.0 || y == 0.0 || z == 0.0) {
|
||||
std::string error("Failed to convert GPS position to UTM for " + imageFilename);
|
||||
throw UtmExtractorException(error);
|
||||
}
|
||||
coords.push_back(Coord(x, y, z));
|
||||
}
|
||||
}
|
||||
imageListStream.close();
|
||||
|
||||
// Calculate average
|
||||
double dx = 0.0, dy = 0.0;
|
||||
double num = static_cast<double>(coords.size());
|
||||
for (std::vector<Coord>::iterator iter = coords.begin(); iter != coords.end(); ++iter) {
|
||||
dx += iter->x/num;
|
||||
dy += iter->y/num;
|
||||
}
|
||||
|
||||
dx = floor(dx);
|
||||
dy = floor(dy);
|
||||
|
||||
// Open output file
|
||||
std::ofstream outputCoordStream(outputCoordFileName_.c_str());
|
||||
if (!outputCoordStream.good()) {
|
||||
throw UtmExtractorException("Failed to open " + outputCoordFileName_ + " for writing.");
|
||||
}
|
||||
outputCoordStream.precision(10);
|
||||
|
||||
// Write coordinate file
|
||||
outputCoordStream << "WGS84 UTM " << utmZone << hemisphere << std::endl;
|
||||
outputCoordStream << dx << " " << dy << std::endl;
|
||||
for (std::vector<Coord>::iterator iter = coords.begin(); iter != coords.end(); ++iter) {
|
||||
outputCoordStream << (iter->x - dx) << " " << (iter->y - dy) << " " << iter->z << std::endl;
|
||||
}
|
||||
|
||||
outputCoordStream.close();
|
||||
|
||||
}
|
||||
|
||||
void UtmExtractor::convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere)
|
||||
{
|
||||
// Create WGS84 longitude/latitude coordinate system
|
||||
projPJ pjLatLon = pj_init_plus("+proj=latlong +datum=WGS84");
|
||||
if (!pjLatLon) {
|
||||
throw UtmExtractorException("Couldn't create WGS84 coordinate system with PROJ.4.");
|
||||
}
|
||||
|
||||
// Calculate UTM zone if it's set to magic 99
|
||||
// NOTE: Special UTM cases in Norway/Svalbard not supported here
|
||||
if (utmZone == 99) {
|
||||
utmZone = ((static_cast<int>(floor((lon + 180.0)/6.0)) % 60) + 1);
|
||||
if (lat < 0)
|
||||
hemisphere = 'S';
|
||||
else
|
||||
hemisphere = 'N';
|
||||
}
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << utmZone;
|
||||
if (hemisphere == 'S')
|
||||
ostr << " +south";
|
||||
|
||||
// Create UTM coordinate system
|
||||
projPJ pjUtm = pj_init_plus(("+proj=utm +datum=WGS84 +zone=" + ostr.str()).c_str());
|
||||
if (!pjUtm) {
|
||||
throw UtmExtractorException("Couldn't create UTM coordinate system with PROJ.4.");
|
||||
}
|
||||
|
||||
// Convert to radians
|
||||
x = lon * DEG_TO_RAD;
|
||||
y = lat * DEG_TO_RAD;
|
||||
z = alt;
|
||||
|
||||
// Transform
|
||||
int res = pj_transform(pjLatLon, pjUtm, 1, 1, &x, &y, &z);
|
||||
if (res != 0) {
|
||||
throw UtmExtractorException("Failed to transform coordinates");
|
||||
}
|
||||
}
|
||||
|
||||
void UtmExtractor::parsePosition(Exiv2::ExifData &exifData, double &lon, double &lat, double &alt)
|
||||
{
|
||||
Exiv2::Exifdatum& latitudeTag = exifData["Exif.GPSInfo.GPSLatitude"];
|
||||
Exiv2::Exifdatum& latitudeRef = exifData["Exif.GPSInfo.GPSLatitudeRef"];
|
||||
Exiv2::Exifdatum& longitudeTag = exifData["Exif.GPSInfo.GPSLongitude"];
|
||||
Exiv2::Exifdatum& longitudeRef = exifData["Exif.GPSInfo.GPSLongitudeRef"];
|
||||
Exiv2::Exifdatum& altitudeTag = exifData["Exif.GPSInfo.GPSAltitude"];
|
||||
Exiv2::Exifdatum& altitudeRef = exifData["Exif.GPSInfo.GPSAltitudeRef"];
|
||||
|
||||
// Latitude: parse into a double
|
||||
if (latitudeTag.count() < 3)
|
||||
throw UtmExtractorException("Image is missing GPS Latitude data");
|
||||
else {
|
||||
Exiv2::URational rLat[] = {latitudeTag.toRational(0), latitudeTag.toRational(1), latitudeTag.toRational(2)};
|
||||
bool south = (strcmp(latitudeRef.toString().c_str(), "S") == 0);
|
||||
double degrees, minutes, seconds;
|
||||
|
||||
degrees = (double)rLat[0].first / (double)rLat[0].second;
|
||||
minutes = (double)rLat[1].first / (double)rLat[1].second / 60.0;
|
||||
seconds = (double)rLat[2].first / (double)rLat[2].second / 3600.0;
|
||||
lat = (south ? -1 : 1) * (degrees + minutes + seconds);
|
||||
}
|
||||
|
||||
// Longitude
|
||||
if (longitudeTag.count() < 3)
|
||||
throw UtmExtractorException("Image is missing GPS Longitude data");
|
||||
else {
|
||||
Exiv2::URational rLon[] = {longitudeTag.toRational(0), longitudeTag.toRational(1), longitudeTag.toRational(2)};
|
||||
bool west = (strcmp(longitudeRef.toString().c_str(), "W") == 0);
|
||||
double degrees, minutes, seconds;
|
||||
|
||||
degrees = (double)rLon[0].first / (double)rLon[0].second;
|
||||
minutes = (double)rLon[1].first / (double)rLon[1].second / 60.0;
|
||||
seconds = (double)rLon[2].first / (double)rLon[2].second / 3600.0;
|
||||
lon = (west ? -1 : 1) * (degrees + minutes + seconds);
|
||||
}
|
||||
|
||||
// Altitude
|
||||
if (altitudeTag.count() < 1)
|
||||
throw UtmExtractorException("Image is missing GPS Altitude data");
|
||||
else {
|
||||
Exiv2::URational rAlt = altitudeTag.toRational(0);
|
||||
bool below = (altitudeRef.count() >= 1 && altitudeRef.toLong() == 1);
|
||||
alt = (below ? -1 : 1) * (double) rAlt.first / (double) rAlt.second;
|
||||
}
|
||||
}
|
||||
|
||||
void UtmExtractor::printHelp()
|
||||
{
|
||||
log_.setIsPrintingInCout(true);
|
||||
|
||||
log_ << "Purpose:\n";
|
||||
log_ << "Create a coordinate file containing the GPS positions of all cameras to be used later in the ODM toolchain for automatic georeferecing.\n";
|
||||
|
||||
log_ << "Usage:\n";
|
||||
log_ << "The program requires paths to a image list file, a image folder path and an output textfile to store the results.\n";
|
||||
|
||||
log_ << "The following flags are available:\n";
|
||||
log_ << "Call the program with flag \"-help\", or without parameters to print this message, or check any generated log file.\n";
|
||||
log_ << "Call the program with flag \"-verbose\", to print log messages in the standard output.\n\n";
|
||||
|
||||
log_ << "Parameters are specified as: \"-<argument name> <argument>\", (without <>), and the following parameters are configurable:\n";
|
||||
log_ << "\"-imageListFile <path>\" (mandatory)\n";
|
||||
log_ << "Path to the list containing the image names used in the bundle.out file.\n";
|
||||
|
||||
log_ << "\"-imagesPath <path>\" (mandatory)\n";
|
||||
log_ << "Path folder containing all images in the imageListFile.\n";
|
||||
|
||||
log_ << "\"-outputCoordFile <path>\" (mandatory)\n";
|
||||
log_ << "Path output textfile.\n";
|
||||
|
||||
log_.setIsPrintingInCout(false);
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// Logging
|
||||
#include "Logger.hpp"
|
||||
#include <exiv2/exiv2.hpp>
|
||||
|
||||
|
||||
/*!
|
||||
* \breif The Coord struct Class used in UtmExtractor to extract GPS positions from images and ODM output
|
||||
*/
|
||||
struct Coord
|
||||
{
|
||||
double x, y, z;
|
||||
Coord(double ix, double iy, double iz) : x(ix), y(iy), z(iz) {}
|
||||
};
|
||||
|
||||
class UtmExtractor
|
||||
{
|
||||
public:
|
||||
UtmExtractor();
|
||||
~UtmExtractor();
|
||||
|
||||
/*!
|
||||
* \brief run Runs the texturing functionality using the provided input arguments.
|
||||
* For a list of the accepted arguments, please 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:
|
||||
|
||||
/*!
|
||||
* \brief parseArguments Parses command line arguments.
|
||||
* \param argc Application argument count.
|
||||
* \param argv Argument values.
|
||||
*/
|
||||
void parseArguments(int argc, char **argv);
|
||||
|
||||
/*!
|
||||
* \breif extractUtm Performs the extraction of coordinates inside the run function.
|
||||
*/
|
||||
void extractUtm();
|
||||
|
||||
/*!
|
||||
* /brief Static method that converts a WGS84 longitude/latitude coordinate in decimal degrees to UTM.
|
||||
*
|
||||
* \param lon The longitude in decimal degrees (negative if western hemisphere).
|
||||
* \param lat The latitude in decimal degrees (negative if southern hemisphere).
|
||||
* \param alt The altitude in meters.
|
||||
* \param x Output parameter, the easting UTM value in meters.
|
||||
* \param y Output parameter, the northing UTM value in meters.
|
||||
* \param utmZone Input or output parameter, the UTM zone. Set to 99 for automatic selection.
|
||||
* \param hemisphere Input or output parameter, 'N' for norther hemisphere, 'S' for southern. Automatically selected if utmZone is 99.
|
||||
*
|
||||
* \returns True if successful (otherwise output parameters are 0)
|
||||
*/
|
||||
static void convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere);
|
||||
|
||||
/*!
|
||||
* \brief Static method that parses a GPS position from jhead data.
|
||||
*
|
||||
* \param jheadDataStream Jhead data stream with EXIF information.
|
||||
* \param lon Output parameter, the longitude in decimal degrees.
|
||||
* \param lat Output parameter, the latitude in decimal degrees.
|
||||
* \param alt Output parameter, the altitude in meters.
|
||||
*
|
||||
* \returns True if successful (otherwise output parameters are 0)
|
||||
*/
|
||||
static void parsePosition(Exiv2::ExifData &exifData, double &lon, double &lat, double &alt);
|
||||
|
||||
/*!
|
||||
* \brief printHelp Prints help, explaining usage. Can be shown by calling the program with arguments: "-help".
|
||||
*/
|
||||
void printHelp();
|
||||
|
||||
std::string imageListFileName_; /**< Path to the image list. */
|
||||
std::string outputCoordFileName_; /**< Path to the file to store the output textfile. */
|
||||
std::string imagesPath_; /**< Path to the folder with all images in the image list. */
|
||||
|
||||
Logger log_; /**< Logging object. */
|
||||
std::string logFile_; /**< Path to store the log file. */
|
||||
|
||||
};
|
||||
|
||||
class UtmExtractorException : public std::exception
|
||||
{
|
||||
public:
|
||||
UtmExtractorException() : message("Error in OdmExtractUtm") {}
|
||||
UtmExtractorException(std::string msgInit) : message("Error in OdmExtractUtm:\n" + msgInit) {}
|
||||
~UtmExtractorException() throw() {}
|
||||
virtual const char* what() const throw() {return message.c_str(); }
|
||||
|
||||
private:
|
||||
std::string message; /**< The error message. */
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
|
||||
#include "UtmExtractor.hpp"
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
UtmExtractor utmExtractor;
|
||||
return utmExtractor.run(argc, argv);
|
||||
}
|
|
@ -120,21 +120,6 @@ class ODMLoadDatasetCell(ecto.Cell):
|
|||
# Generate UTM from images
|
||||
try:
|
||||
if not io.file_exists(tree.odm_georeferencing_coords) or rerun_cell:
|
||||
verbose = '-verbose' if self.params.verbose else ''
|
||||
kwargs = {
|
||||
'bin': context.odm_modules_path,
|
||||
'imgs': tree.dataset_raw,
|
||||
'imgs_list': tree.dataset_list,
|
||||
'coords': tree.odm_georeferencing_coords + '.old.txt',
|
||||
'log': tree.odm_georeferencing_utm_log,
|
||||
'verbose': verbose
|
||||
}
|
||||
|
||||
# TODO: remove call to odm_extract_utm
|
||||
system.run('{bin}/odm_extract_utm -imagesPath {imgs}/ '
|
||||
'-imageListFile {imgs_list} -outputCoordFile {coords} {verbose} '
|
||||
'-logFile {log}'.format(**kwargs))
|
||||
|
||||
location.extract_utm_coords(photos, tree.dataset_raw, tree.odm_georeferencing_coords)
|
||||
else:
|
||||
log.ODM_INFO("Coordinates file already exist: %s" % tree.odm_georeferencing_coords)
|
||||
|
|
Ładowanie…
Reference in New Issue