SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
CVImageGeoTiff.cpp
Go to the documentation of this file.
1 /**
2  * \file cv/CVImageGeoTiff.cpp
3  * \date Spring 2017
4  * \authors Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8  */
9 
10 #include <CVImageGeoTiff.h>
11 #include <json.hpp>
12 #include <Utils.h>
13 #include <SL.h>
14 
16 
17 //-----------------------------------------------------------------------------
19 {
20  _noDataValue = 0.0;
21 }
22 //-----------------------------------------------------------------------------
24 {
25  clearData();
26 }
27 //-----------------------------------------------------------------------------
28 //! Loads a GEOTiff file into the OpenCV image matrix
29 void CVImageGeoTiff::loadGeoTiff(const string& geoTiffFile)
30 {
31 #ifndef __EMSCRIPTEN__
32  string msg;
33 
34  // check if the GEOTiff file exists
35  if (!Utils::fileExists(geoTiffFile))
36  {
37  msg = "CVImageGeoTiff::loadGeoTiff: File not found: " + geoTiffFile;
38  Utils::exitMsg("SLProject",
39  msg.c_str(),
40  __LINE__,
41  __FILE__);
42  }
43 
44  // check if the GEOTiff json file exists
45  string jsonFileName = Utils::getPath(geoTiffFile) +
46  Utils::getFileNameWOExt(geoTiffFile) +
47  ".json";
48  if (!Utils::fileExists(jsonFileName))
49  {
50  msg = "CVImageGeoTiff::loadGeoTiff: JSON File not found: " + jsonFileName;
51  msg += "\nA GEOTiff file must have a JSON file aside with the same name.";
52  msg += "\nYou can generate this JSON file with the tool gdalinfo.";
53  Utils::exitMsg("SLProject",
54  msg.c_str(),
55  __LINE__,
56  __FILE__);
57  }
58 
59  // Read the geo tiff image with OpenCV
60  cv::Mat imgGeoTiff = cv::imread(geoTiffFile,
61  cv::IMREAD_LOAD_GDAL | cv::IMREAD_ANYDEPTH);
62 
63  if (imgGeoTiff.type() != CV_32FC1)
64  Utils::exitMsg("SLProject",
65  "GEOTiff image must be of 32-bit float type.",
66  __LINE__,
67  __FILE__);
68 
69  // Read the JSON file
70  std::ifstream jsonFile(jsonFileName);
71  json jsonData;
72  string description;
73  string geocsc;
74  vector<int> size;
75  vector<double> upperLeft;
76  vector<double> lowerRight;
77 
78  // Reading values from json
79  try
80  {
81  jsonFile >> jsonData;
82  description = jsonData["description"].get<string>();
83  geocsc = jsonData["coordinateSystem"]["wkt"].get<string>();
84  size = jsonData["size"].get<vector<int>>();
85  upperLeft = jsonData["cornerCoordinates"]["upperLeft"].get<vector<double>>();
86  lowerRight = jsonData["cornerCoordinates"]["lowerRight"].get<vector<double>>();
87  _noDataValue = jsonData["bands"][0]["noDataValue"].get<double>();
88  }
89  catch (json::exception& e)
90  {
91  msg = "Error reading JSON-File: " + jsonFileName;
92  msg += "\nException: ";
93  msg += e.what();
94  Utils::exitMsg("SLProject",
95  msg.c_str(),
96  __LINE__,
97  __FILE__);
98  }
99 
100  // Check some correspondences between image file an json file
101  if (size.size() < 2 || size[0] != imgGeoTiff.cols || size[1] != imgGeoTiff.rows)
102  {
103  msg = "Mismatch between geotiff image size and size json tag:";
104  msg += "\nGEOTiff image width : " + to_string(imgGeoTiff.cols);
105  msg += "\nGEOTiff image height: " + to_string(imgGeoTiff.rows);
106  msg += "\nJSON Size tag[0] : " + to_string(size[0]);
107  msg += "\nJSON Size tag[1] : " + to_string(size[1]);
108  Utils::exitMsg("SLProject",
109  msg.c_str(),
110  __LINE__,
111  __FILE__);
112  }
113 
114  if (!Utils::containsString(geocsc, "WGS 84") &&
115  !Utils::containsString(geocsc, "WGS_1984"))
116  {
117  msg = "GeoTiff file seams not have WGS84 coordinates.";
118  Utils::exitMsg("SLProject",
119  msg.c_str(),
120  __LINE__,
121  __FILE__);
122  }
123 
124  _cvMat = imgGeoTiff.clone();
125  _format = cvType2glPixelFormat(imgGeoTiff.type());
126 
127  _upperleftLatLonAlt[0] = upperLeft[1]; // We store first latitude in degrees! (N)
128  _upperleftLatLonAlt[1] = upperLeft[0]; // and then longitude in degrees (W)
129  _upperleftLatLonAlt[2] = _cvMat.at<float>(0, 0); // and then altitude in m from the image
130  _lowerRightLatLonAlt[0] = lowerRight[1]; // we store first latitude in degrees! (S)
131  _lowerRightLatLonAlt[1] = lowerRight[0]; // and then longitude in degrees (E)
132  _lowerRightLatLonAlt[2] = _cvMat.at<float>(_cvMat.rows - 1, _cvMat.cols - 1);
133 #endif
134 }
135 //-----------------------------------------------------------------------------
136 //! Returns the altitude in m at the given position in WGS84 latitude-longitude
138  double lonDEG) const
139 {
140  double dLatDEG = _upperleftLatLonAlt[0] - _lowerRightLatLonAlt[0];
141  double dLonDEG = _lowerRightLatLonAlt[1] - _upperleftLatLonAlt[1];
142  double latPerPix = dLatDEG / (double)_cvMat.rows;
143  double lonPerPix = dLonDEG / (double)_cvMat.cols;
144 
145  double offsetLat = latDEG - _lowerRightLatLonAlt[0];
146  double offsetLon = lonDEG - _upperleftLatLonAlt[1];
147 
148  double pixPosLat = offsetLat / latPerPix; // pixels from bottom
149  double pixPosLon = offsetLon / lonPerPix; // pixels from left
150 
151  // pixels are top-left coordinates in OpenCV
152  pixPosLat = _cvMat.rows - pixPosLat;
153 
154  if (pixPosLat < 0.0 || pixPosLat > _cvMat.rows - 1.0)
155  {
156  SL_LOG("Invalid pixPosLat %3.2f", pixPosLat);
157  pixPosLat = 0;
158  }
159  if (pixPosLon < 0.0 || pixPosLon > _cvMat.cols - 1.0)
160  {
161  SL_LOG("Invalid pixPosLon %3.2f", pixPosLon);
162  pixPosLon = 0;
163  }
164 
165  // get subpixel accurate interpolated height value
166  cv::Point2f pt((float)pixPosLon, (float)pixPosLat);
167  cv::Mat patch;
168  cv::getRectSubPix(_cvMat, cv::Size(1, 1), pt, patch);
169 
170  float heightMatPix = _cvMat.at<float>((int)pixPosLat, (int)pixPosLon);
171  float heightMatSubPix = patch.at<float>(0, 0);
172  return heightMatSubPix;
173 }
174 //-----------------------------------------------------------------------------
nlohmann::json json
#define SL_LOG(...)
Definition: SL.h:233
CVVec3d _upperleftLatLonAlt
CVVec3d _lowerRightLatLonAlt
Upper-left corner of DEM in WGS84 coords.
double _noDataValue
Lower-right corner of DEM in WGS84 coords.
void loadGeoTiff(const string &filename)
Loads a GEOTiff file into the OpenCV image matrix.
float getAltitudeAtLatLon(double lat, double lon) const
Returns the altitude in m at the given position in WGS84 latitude-longitude.
CVPixelFormatGL _format
OpenGL pixel format.
Definition: CVImage.h:144
void clearData()
Deletes all data and resets the image parameters.
Definition: CVImage.cpp:102
static CVPixelFormatGL cvType2glPixelFormat(int cvType)
Converts OpenCV mat type to OpenGL pixel format.
Definition: CVImage.cpp:522
CVMat _cvMat
OpenCV mat matrix image type.
Definition: CVImage.h:143
bool fileExists(const string &pathfilename)
Returns true if a file exists.
Definition: Utils.cpp:897
bool containsString(const string &container, const string &search)
Returns true if container contains the search string.
Definition: Utils.cpp:345
string getFileNameWOExt(const string &pathFilename)
Returns the filename without extension.
Definition: Utils.cpp:616
string getPath(const string &pathFilename)
Returns the path w. '\' of path-filename string.
Definition: Utils.cpp:392
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135