AliceVision
Photogrammetric Computer Vision Framework
Descriptor.hpp
1 // This file is part of the AliceVision project.
2 // Copyright (c) 2016 AliceVision contributors.
3 // Copyright (c) 2012 openMVG contributors.
4 // This Source Code Form is subject to the terms of the Mozilla Public License,
5 // v. 2.0. If a copy of the MPL was not distributed with this file,
6 // You can obtain one at https://mozilla.org/MPL/2.0/.
7 
8 #pragma once
9 
10 #include <aliceVision/numeric/numeric.hpp>
11 
12 #include <iostream>
13 #include <iterator>
14 #include <fstream>
15 #include <string>
16 #include <vector>
17 #include <exception>
18 
19 namespace aliceVision {
20 namespace feature {
21 
28 template<typename T, std::size_t N>
30 {
31  public:
32  typedef Descriptor<T, N> This;
33  typedef T value_type;
34  typedef T bin_type;
35  typedef std::size_t size_type;
36 
38  static const size_type static_size = N;
39 
41  inline Descriptor() {}
42 
43  inline Descriptor(T defaultValue)
44  {
45  for (size_type i = 0; i < N; ++i)
46  data[i] = defaultValue;
47  }
48 
50  inline size_type size() const { return N; }
51 
53  inline bin_type& operator[](std::size_t i) { return data[i]; }
54  inline bin_type operator[](std::size_t i) const { return data[i]; }
55 
56  bin_type & at(std::size_t i) { return data[i]; }
57 
58  // Atomic addition between two descriptors
59  inline This& operator+=(const This other)
60  {
61  for (size_type i = 0; i < size(); ++i)
62  data[i] += other[i];
63  return *this;
64  }
65 
66  // Division between two descriptors
67  inline This operator/(const This other) const
68  {
69  This res;
70  for (size_type i = 0; i < size(); ++i)
71  res[i] = data[i] / other[i];
72  return res;
73  }
74 
75  inline This& operator*=(const value_type scalar)
76  {
77  for (size_type i = 0; i < size(); ++i)
78  data[i] *= scalar;
79  return *this;
80  }
81 
82  bool operator==(const Descriptor& other) const { return std::equal(data, data + N, other.data); }
83 
84  inline bin_type* getData() const { return (bin_type*)(&data[0]); }
85 
87  std::ostream& print(std::ostream& os) const;
89  std::istream& read(std::istream& in);
90 
91  template<class Archive>
92  void save(Archive& archive) const
93  {
94  std::vector<T> array(data, data + N);
95  archive(array);
96  }
97 
98  template<class Archive>
99  void load(Archive& archive)
100  {
101  std::vector<T> array(N);
102  archive(array);
103  std::memcpy(data, array.data(), sizeof(T) * N);
104  }
105 
106  private:
107  bin_type data[N];
108 };
109 
110 // Output stream definition
111 template<typename T, std::size_t N>
112 inline std::ostream& operator<<(std::ostream& out, const Descriptor<T, N>& obj)
113 {
114  return obj.print(out); // simply call the print method.
115 }
116 
117 // Input stream definition
118 template<typename T, std::size_t N>
119 inline std::istream& operator>>(std::istream& in, Descriptor<T, N>& obj)
120 {
121  return obj.read(in); // simply call the read method.
122 }
123 
124 //-- Use specialization to handle unsigned char case.
125 //-- We do not want confuse unsigned char value with the spaces written in the file
126 
127 template<typename T>
128 inline std::ostream& printT(std::ostream& os, T* tab, size_t N)
129 {
130  std::copy(tab, &tab[N], std::ostream_iterator<T>(os, " "));
131  return os;
132 }
133 
134 template<>
135 inline std::ostream& printT<unsigned char>(std::ostream& os, unsigned char* tab, size_t N)
136 {
137  for (size_t i = 0; i < N; ++i)
138  os << (int)tab[i] << " ";
139  return os;
140 }
141 
142 template<typename T>
143 inline std::istream& readT(std::istream& is, T* tab, size_t N)
144 {
145  for (size_t i = 0; i < N; ++i)
146  is >> tab[i];
147  return is;
148 }
149 
150 template<>
151 inline std::istream& readT<unsigned char>(std::istream& is, unsigned char* tab, size_t N)
152 {
153  int temp = -1;
154  for (size_t i = 0; i < N; ++i)
155  {
156  is >> temp;
157  tab[i] = (unsigned char)temp;
158  }
159  return is;
160 }
161 
162 template<typename T, std::size_t N>
163 std::ostream& Descriptor<T, N>::print(std::ostream& os) const
164 {
165  return printT<T>(os, (T*)&data[0], N);
166 }
167 
168 template<typename T, std::size_t N>
169 std::istream& Descriptor<T, N>::read(std::istream& in)
170 {
171  return readT<T>(in, (T*)&data[0], N);
172 }
173 
175 template<typename DescriptorsT>
176 inline void loadDescsFromFile(const std::string& sfileNameDescs, DescriptorsT& vec_desc)
177 {
178  vec_desc.clear();
179 
180  std::ifstream fileIn(sfileNameDescs);
181  if (!fileIn.is_open())
182  throw std::runtime_error("Can't load descriptor file, can't open '" + sfileNameDescs + "' !");
183 
184  std::copy(std::istream_iterator<typename DescriptorsT::value_type>(fileIn),
185  std::istream_iterator<typename DescriptorsT::value_type>(),
186  std::back_inserter(vec_desc));
187 
188  if (fileIn.bad())
189  throw std::runtime_error("Can't load descriptor file, '" + sfileNameDescs + "' is incorrect !");
190 
191  fileIn.close();
192 }
193 
195 template<typename DescriptorsT>
196 inline void saveDescsToFile(const std::string& sfileNameDescs, DescriptorsT& vec_desc)
197 {
198  std::ofstream file(sfileNameDescs);
199  if (!file.is_open())
200  throw std::runtime_error("Can't save descriptor file, can't open '" + sfileNameDescs + "' !");
201 
202  std::copy(vec_desc.begin(), vec_desc.end(), std::ostream_iterator<typename DescriptorsT::value_type>(file, "\n"));
203 
204  if (!file.good())
205  throw std::runtime_error("Can't save descriptor file, '" + sfileNameDescs + "' is incorrect !");
206 
207  file.close();
208 }
209 
217 template<typename DescFrom, typename DescTo>
218 void convertDesc(const DescFrom& descFrom, DescTo& descTo)
219 {
220  typename DescFrom::bin_type* ptrFrom = descFrom.getData();
221  typename DescTo::bin_type* ptrTo = descTo.getData();
222 
223  for (size_t i = 0; i < DescFrom::static_size; ++i)
224  {
225  ptrTo[i] = typename DescTo::value_type(ptrFrom[i]);
226  }
227 }
228 
246 template<typename DescriptorT, typename FileDescriptorT = DescriptorT>
247 inline void loadDescsFromBinFile(const std::string& sfileNameDescs, std::vector<DescriptorT>& vec_desc, bool append = false, const int Nmax = 0)
248 {
249  if (!append) // for compatibility
250  vec_desc.clear();
251 
252  std::ifstream fileIn(sfileNameDescs, std::ios::in | std::ios::binary);
253 
254  if (!fileIn.is_open())
255  throw std::runtime_error("Can't load descriptor binary file, can't open '" + sfileNameDescs + "' !");
256 
257  // Read the number of descriptor in the file
258  std::size_t cardDesc = 0;
259  fileIn.read((char*)&cardDesc, sizeof(std::size_t));
260 
261  std::size_t previousSize = vec_desc.size();
262 
263  if (Nmax != 0)
264  vec_desc.resize(vec_desc.size() + std::min((int)cardDesc, Nmax));
265  else
266  vec_desc.resize(vec_desc.size() + cardDesc);
267  typename std::vector<DescriptorT>::iterator begin = vec_desc.begin();
268  std::advance(begin, previousSize);
269 
270  // Compute the memory size of one descriptor
271  constexpr std::size_t oneDescSize = FileDescriptorT::static_size * sizeof(typename FileDescriptorT::bin_type);
272 
273  FileDescriptorT fileDescriptor;
274  for (typename std::vector<DescriptorT>::iterator iter = begin; iter != vec_desc.end(); ++iter)
275  {
276  fileIn.read((char*)fileDescriptor.getData(), oneDescSize);
277  convertDesc<FileDescriptorT, DescriptorT>(fileDescriptor, *iter);
278  }
279 
280  if (fileIn.bad())
281  throw std::runtime_error("Can't load descriptor binary file, '" + sfileNameDescs + "' is incorrect !");
282 
283  fileIn.close();
284 }
285 
287 template<typename DescriptorsT>
288 inline void saveDescsToBinFile(const std::string& sfileNameDescs, DescriptorsT& vec_desc)
289 {
290  typedef typename DescriptorsT::value_type VALUE;
291 
292  std::ofstream file(sfileNameDescs, std::ios::out | std::ios::binary);
293 
294  if (!file.is_open())
295  throw std::runtime_error("Can't save descriptor binary file, can't open '" + sfileNameDescs + "' !");
296 
297  // Write the number of descriptor
298  const std::size_t cardDesc = vec_desc.size();
299  file.write((const char*)&cardDesc, sizeof(std::size_t));
300  for (typename DescriptorsT::const_iterator iter = vec_desc.begin(); iter != vec_desc.end(); ++iter)
301  {
302  file.write((const char*)(*iter).getData(), VALUE::static_size * sizeof(typename VALUE::bin_type));
303  }
304 
305  if (!file.good())
306  throw std::runtime_error("Can't save descriptor binary file, '" + sfileNameDescs + "' is incorrect !");
307 
308  file.close();
309 }
310 
311 } // namespace feature
312 } // namespace aliceVision
aliceVision::feature::Descriptor::size
size_type size() const
capacity
Definition: Descriptor.hpp:50
aliceVision::feature::Descriptor::Descriptor
Descriptor()
Constructor.
Definition: Descriptor.hpp:41
aliceVision::feature::Descriptor::read
std::istream & read(std::istream &in)
Istream interface.
Definition: Descriptor.hpp:169
aliceVision::feature::Descriptor::operator[]
bin_type & operator[](std::size_t i)
Mutable and non-mutable bin getters.
Definition: Descriptor.hpp:53
aliceVision
Definition: checkerDetector.cpp:32
aliceVision::feature::Descriptor
Definition: Descriptor.hpp:29
aliceVision::feature::Descriptor::static_size
static const size_type static_size
Compile-time length of the descriptor.
Definition: Descriptor.hpp:38
aliceVision::feature::Descriptor::print
std::ostream & print(std::ostream &os) const
Ostream interface.
Definition: Descriptor.hpp:163