ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
image_reader.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "base/image_reader.h"
33 
34 #include "base/camera_models.h"
35 #include "util/misc.h"
36 
37 namespace colmap {
38 
42  const int model_id = CameraModelNameToId(camera_model);
43  if (!camera_params.empty()) {
45  CameraModelVerifyParams(model_id, CSVToVector<double>(camera_params)));
46  }
47  return true;
48 }
49 
51  : options_(options), database_(database), image_index_(0) {
52  CHECK(options_.Check());
53 
54  // Ensure trailing slash, so that we can build the correct image name.
55  options_.image_path =
56  EnsureTrailingSlash(StringReplace(options_.image_path, "\\", "/"));
57 
58  // Get a list of all files in the image path, sorted by image name.
59  if (options_.image_list.empty()) {
60  options_.image_list = GetRecursiveFileList(options_.image_path);
61  std::sort(options_.image_list.begin(), options_.image_list.end());
62  } else {
63  if (!std::is_sorted(options_.image_list.begin(),
64  options_.image_list.end())) {
65  std::sort(options_.image_list.begin(), options_.image_list.end());
66  }
67  for (auto& image_name : options_.image_list) {
68  image_name = JoinPaths(options_.image_path, image_name);
69  }
70  }
71 
72  if (static_cast<camera_t>(options_.existing_camera_id) != kInvalidCameraId) {
73  CHECK(database->ExistsCamera(options_.existing_camera_id));
74  prev_camera_ = database->ReadCamera(options_.existing_camera_id);
75  } else {
76  // Set the manually specified camera parameters.
77  prev_camera_.SetCameraId(kInvalidCameraId);
78  prev_camera_.SetModelIdFromName(options_.camera_model);
79  if (!options_.camera_params.empty()) {
80  CHECK(prev_camera_.SetParamsFromString(options_.camera_params));
81  prev_camera_.SetPriorFocalLength(true);
82  }
83  }
84 }
85 
87  Bitmap* bitmap, Bitmap* mask) {
88  CHECK_NOTNULL(camera);
89  CHECK_NOTNULL(image);
90  CHECK_NOTNULL(bitmap);
91 
92  image_index_ += 1;
93  CHECK_LE(image_index_, options_.image_list.size());
94 
95  const std::string image_path = options_.image_list.at(image_index_ - 1);
96 
97  DatabaseTransaction database_transaction(database_);
98 
100  // Set the image name.
102 
103  image->SetName(image_path);
104  image->SetName(StringReplace(image->Name(), "\\", "/"));
105  image->SetName(
106  image->Name().substr(options_.image_path.size(),
107  image->Name().size() - options_.image_path.size()));
108 
109  const std::string image_folder = GetParentDir(image->Name());
110 
112  // Check if image already read.
114 
115  const bool exists_image = database_->ExistsImageWithName(image->Name());
116 
117  if (exists_image) {
118  *image = database_->ReadImageWithName(image->Name());
119  const bool exists_keypoints = database_->ExistsKeypoints(image->ImageId());
120  const bool exists_descriptors =
121  database_->ExistsDescriptors(image->ImageId());
122 
123  if (exists_keypoints && exists_descriptors) {
124  return Status::IMAGE_EXISTS;
125  }
126  }
127 
129  // Read image.
131 
132  if (!bitmap->Read(image_path, false)) {
133  return Status::BITMAP_ERROR;
134  }
135 
137  // Read mask.
139 
140  if (mask && !options_.mask_path.empty()) {
141  const std::string mask_path =
142  JoinPaths(options_.mask_path,
143  GetRelativePath(options_.image_path, image_path) + ".png");
144  if (ExistsFile(mask_path) && !mask->Read(mask_path, false)) {
145  // NOTE: Maybe introduce a separate error type MASK_ERROR?
146  return Status::BITMAP_ERROR;
147  }
148  }
149 
151  // Check for well-formed data.
153 
154  if (exists_image) {
155  const Camera current_camera = database_->ReadCamera(image->CameraId());
156 
157  if (options_.single_camera && prev_camera_.CameraId() != kInvalidCameraId &&
158  (current_camera.Width() != prev_camera_.Width() ||
159  current_camera.Height() != prev_camera_.Height())) {
161  }
162 
163  if (static_cast<size_t>(bitmap->Width()) != current_camera.Width() ||
164  static_cast<size_t>(bitmap->Height()) != current_camera.Height()) {
166  }
167 
168  prev_camera_ = current_camera;
169 
170  } else {
172  // Check image dimensions.
174 
175  if (prev_camera_.CameraId() != kInvalidCameraId &&
176  ((options_.single_camera && !options_.single_camera_per_folder) ||
177  (options_.single_camera_per_folder &&
178  image_folder == prev_image_folder_)) &&
179  (prev_camera_.Width() != static_cast<size_t>(bitmap->Width()) ||
180  prev_camera_.Height() != static_cast<size_t>(bitmap->Height()))) {
182  }
183 
185  // Read camera model and check for consistency if it exists
187  std::string camera_model;
188  const bool valid_camera_model = bitmap->ExifCameraModel(&camera_model);
189  if (camera_model_to_id_.count(camera_model) > 0) {
190  const Camera& cam =
191  database_->ReadCamera(camera_model_to_id_.at(camera_model));
192  if (cam.Width() != static_cast<size_t>(bitmap->Width()) ||
193  cam.Height() != static_cast<size_t>(bitmap->Height())) {
195  }
196  prev_camera_ = cam;
197  }
198 
200  // Extract camera model and focal length
202 
203  if (prev_camera_.CameraId() == kInvalidCameraId ||
204  options_.single_camera_per_image ||
205  (!options_.single_camera && !options_.single_camera_per_folder &&
206  static_cast<camera_t>(options_.existing_camera_id) ==
208  camera_model_to_id_.count(camera_model) == 0) ||
209  (options_.single_camera_per_folder &&
210  image_folders_.count(image_folder) == 0)) {
211  if (options_.camera_params.empty()) {
212  // Extract focal length.
213  double focal_length = 0.0;
214  if (bitmap->ExifFocalLength(&focal_length)) {
215  prev_camera_.SetPriorFocalLength(true);
216  } else {
217  focal_length = options_.default_focal_length_factor *
218  std::max(bitmap->Width(), bitmap->Height());
219  prev_camera_.SetPriorFocalLength(false);
220  }
221 
222  prev_camera_.InitializeWithId(prev_camera_.ModelId(), focal_length,
223  bitmap->Width(), bitmap->Height());
224  }
225 
226  prev_camera_.SetWidth(static_cast<size_t>(bitmap->Width()));
227  prev_camera_.SetHeight(static_cast<size_t>(bitmap->Height()));
228 
229  if (!prev_camera_.VerifyParams()) {
231  }
232 
233  prev_camera_.SetCameraId(database_->WriteCamera(prev_camera_));
234  if (valid_camera_model) {
235  camera_model_to_id_[camera_model] = prev_camera_.CameraId();
236  }
237  }
238 
239  image->SetCameraId(prev_camera_.CameraId());
240 
242  // Extract GPS data.
244 
245  if (!bitmap->ExifLatitude(&image->TvecPrior(0)) ||
246  !bitmap->ExifLongitude(&image->TvecPrior(1)) ||
247  !bitmap->ExifAltitude(&image->TvecPrior(2))) {
248  image->TvecPrior().setConstant(std::numeric_limits<double>::quiet_NaN());
249  }
250  }
251 
252  *camera = prev_camera_;
253 
254  image_folders_.insert(image_folder);
255  prev_image_folder_ = image_folder;
256 
257  return Status::SUCCESS;
258 }
259 
260 size_t ImageReader::NextIndex() const { return image_index_; }
261 
262 size_t ImageReader::NumImages() const { return options_.image_list.size(); }
263 
264 } // namespace colmap
std::shared_ptr< core::Tensor > image
bool ExifCameraModel(std::string *camera_model) const
Definition: bitmap.cc:306
bool Read(const std::string &path, const bool as_rgb=true)
Definition: bitmap.cc:485
int Width() const
Definition: bitmap.h:249
bool ExifAltitude(double *altitude) const
Definition: bitmap.cc:472
bool ExifFocalLength(double *focal_length) const
Definition: bitmap.cc:336
int Height() const
Definition: bitmap.h:250
bool ExifLongitude(double *longitude) const
Definition: bitmap.cc:444
bool ExifLatitude(double *latitude) const
Definition: bitmap.cc:416
void SetWidth(const size_t width)
Definition: camera.h:164
bool VerifyParams() const
Definition: camera.cc:182
void InitializeWithId(const int model_id, const double focal_length, const size_t width, const size_t height)
Definition: camera.cc:203
void SetPriorFocalLength(const bool prior)
Definition: camera.h:170
void SetModelIdFromName(const std::string &model_name)
Definition: camera.cc:57
bool SetParamsFromString(const std::string &string)
Definition: camera.cc:172
camera_t CameraId() const
Definition: camera.h:154
int ModelId() const
Definition: camera.h:158
void SetCameraId(const camera_t camera_id)
Definition: camera.h:156
size_t Width() const
Definition: camera.h:160
size_t Height() const
Definition: camera.h:162
void SetHeight(const size_t height)
Definition: camera.h:166
bool ExistsKeypoints(const image_t image_id) const
Definition: database.cc:307
bool ExistsCamera(const camera_t camera_id) const
Definition: database.cc:295
bool ExistsDescriptors(const image_t image_id) const
Definition: database.cc:311
bool ExistsImageWithName(std::string name) const
Definition: database.cc:303
Image ReadImageWithName(const std::string &name) const
Definition: database.cc:407
Camera ReadCamera(const camera_t camera_id) const
Definition: database.cc:365
camera_t WriteCamera(const Camera &camera, const bool use_camera_id=false) const
Definition: database.cc:603
size_t NextIndex() const
ImageReader(const ImageReaderOptions &options, Database *database)
Definition: image_reader.cc:50
Status Next(Camera *camera, Image *image, Bitmap *bitmap, Bitmap *mask)
Definition: image_reader.cc:86
size_t NumImages() const
#define CHECK_OPTION(expr)
Definition: logging.h:20
#define CHECK_OPTION_GT(val1, val2)
Definition: logging.h:34
bool ExistsCameraModelWithName(const std::string &model_name)
std::vector< std::string > GetRecursiveFileList(const std::string &path)
Definition: misc.cc:183
const camera_t kInvalidCameraId
Definition: types.h:75
std::string StringReplace(const std::string &str, const std::string &old_str, const std::string &new_str)
Definition: string.cc:140
std::string GetRelativePath(const std::string &from, const std::string &to)
Definition: misc.cc:132
bool CameraModelVerifyParams(const int model_id, const std::vector< double > &params)
bool ExistsFile(const std::string &path)
Definition: misc.cc:100
std::string JoinPaths(T const &... paths)
Definition: misc.h:128
std::string EnsureTrailingSlash(const std::string &str)
Definition: misc.cc:40
uint32_t camera_t
Definition: types.h:58
std::string GetParentDir(const std::string &path)
Definition: misc.cc:128
int CameraModelNameToId(const std::string &model_name)
std::vector< std::string > image_list
Definition: image_reader.h:36