MachineIntelligenceCore:Algorithms
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
BMPImporter.hpp
Go to the documentation of this file.
1 
25 #ifndef BMPIMPORTER_HPP_
26 #define BMPIMPORTER_HPP_
27 
28 #include <importers/Importer.hpp>
29 #include <types/TensorTypes.hpp>
30 
31 namespace mic {
32 namespace importers {
33 
40 template <typename eT>
41 class BMPImporter: public mic::importers::Importer< mic::types::Tensor<eT>, unsigned int > {
42 public:
48  BMPImporter(std::string node_name_ = "bmp_importer", std::string data_filename_ = "")
49  : Importer< mic::types::Tensor<eT>, unsigned int >::Importer (node_name_),
50  data_filename("data_filename",data_filename_)
51  {
52  // Register properties - so their values can be overridden (read from the configuration file).
53  registerProperty(data_filename);
54 
55  }
56 
57 
58 
62  virtual ~BMPImporter() { };
63 
68  void setDataFilename(std::string data_filename_) {
69  data_filename = data_filename_;
70  }
71 
76  bool importData() {
77  // Split filename using a semicolon (;) separator.
78  std::vector<std::string> names_array;
79  std::size_t pos = 0, found;
80  while((found = std::string(data_filename).find_first_of(';', pos)) != std::string::npos) {
81  // Get filename from pos to found.
82  names_array.push_back(std::string(data_filename).substr(pos, found - pos));
83  // Move marker.
84  pos = found+1;
85  }//: white
86  // Add last name.
87  names_array.push_back(std::string(data_filename).substr(pos));
88 
89  // Read data from files.
90  for (size_t fi = 0; fi < names_array.size(); ++fi) {
91 
92  // Try to open file with labels.
93  LOG(LSTATUS) << "Opening file: " << names_array[fi];
94  std::ifstream file(names_array[fi], std::ios::in | std::ios::binary);
95  if (!file.is_open()) {
96  LOG(LFATAL) << "Oops! Couldn't find file: " << names_array[fi];
97  return false;
98  }//: else
99 
100 
101  // Got the image and label.
102  LOG(LDEBUG) << "Loading sample: " << names_array[fi];
104 
105  // Add sample to batch.
106  sample_data.push_back(ptr);
107 
108  // Close file
109  file.close();
110 
111  }//: for files.
112 
113  LOG(LINFO) << "Imported " << sample_data.size() << " samples";
114 
115 
116  // Fill labels and indices tables(!)
117  for (size_t i=0; i < sample_data.size(); i++ ){
118  sample_labels.push_back(std::make_shared <unsigned int> (i) );
119  sample_indices.push_back(i);
120  }
121 
122  // Count the classes.
124 
125  LOG(LINFO) << "Data import finished";
126 
127  return true;
128  }
129 
130  mic::types::TensorPtr<float> loadBMP(std::ifstream& file_)
131  {
132  static constexpr size_t HEADER_SIZE = 54;
133 
134  // Read the header.
135  std::array<char, HEADER_SIZE> header;
136  file_.read(header.data(), header.size());
137 
138  // Get parameters.
139  // https://www.gamedev.net/resources/_/technical/game-programming/how-to-load-a-bitmap-r1966
140  // From File information header.
141  uint32_t bfSize = *reinterpret_cast<uint32_t *>(&header[2]);
142  uint32_t bfOffBits = *reinterpret_cast<uint32_t *>(&header[10]);
143  // From Bitmap information header.
144  uint32_t biWidth = *reinterpret_cast<uint32_t *>(&header[18]);
145  uint32_t biHeight = *reinterpret_cast<uint32_t *>(&header[22]);
146  // Number of bits per pixel for colors: 1,4,8 or 24.
147  uint16_t biBitCount = *reinterpret_cast<uint16_t *>(&header[28]);
148 
149  LOG(LDEBUG) << "fileSize: " << bfSize;
150  LOG(LDEBUG) << "dataOffset: " << bfOffBits;
151  LOG(LDEBUG) << "width: " << biWidth;
152  LOG(LDEBUG) << "height: " << biHeight;
153  LOG(LDEBUG) << "depth: " << biBitCount << "-bit";
154 
155  // Set values depending on BitCount.
156  // Number of image channels (3 or 4).
157  size_t img_channels = biBitCount/8;
158  size_t roff, goff, boff;
159  if (biBitCount == 24) {
160  roff = 2;
161  goff = 1;
162  boff = 0;
163  } else if (biBitCount == 32) {
164  roff = 3;
165  goff = 2;
166  boff = 1;
167  } else {
168  LOG(LERROR) << "Unhandel number of bits per pixel: " << biBitCount << "-bit";
169  }
170 
171  // Skip the rest of header.
172  std::vector<char> rest(bfOffBits - HEADER_SIZE);
173  file_.read(rest.data(), rest.size());
174 
175  // Read the "pixels".
176  std::vector<char> img(bfSize - bfOffBits);
177  file_.read(img.data(), img.size());
178 
179  // padWidth is the width of the image plus the extra padding.
180  // Initially set both to the width of the image.
181  size_t padWidth= (size_t)(img_channels*biWidth);
182 
183  // And add any extra space to bring each line to a DWORD boundary
184  while(padWidth%4!=0) {
185  padWidth++;
186  }
187  LOG(LDEBUG) << "padWidth: " << padWidth;
188 
189  // Prepare output tensoroff, goff, boffr.
190  mic::types::TensorPtr<float> ptr = MAKE_TENSOR_PTR(float, biHeight, biWidth, 3 );
191  ptr->zeros();
192  // Get data.
193  float* data_ptr = ptr->data();
194 
195  // Iterate through rows...
196  for (size_t h =0; h < biHeight; h++){
197  // ... and cols.
198  for (size_t w =0; w < padWidth; w+=img_channels) {
199  // Skip the padding.
200  if (w >= img_channels*biWidth) {
201  continue;
202  }
203  size_t i = h*padWidth + w;
204  /*std::cout << "h = " << h << "w = " << w << "i = " << i ;
205  std::cout << " R: " << int(img[i+2] & 0xff) << " G: " << int(img[i+1] & 0xff) << " B: " << int(img[i] & 0xff)
206  << std::endl;*/
207 
208  // Red
209  //(*ptr)({biHeight-1 - h,w/3,0}) = (int(img[i + 2] & 0xff)) / (255.0);
210  data_ptr[(biHeight-1 - h)*biWidth + w/img_channels] = (int(img[i + roff] & 0xff)) / (255.0);
211  // Green
212  //(*ptr)({biHeight-1 - h,w/3,1}) = (int(img[i + 1] & 0xff)) / (255.0);
213  data_ptr[(biHeight-1 - h)*biWidth + w/img_channels + 1*biWidth*biHeight] = (int(img[i + goff] & 0xff)) / (255.0);
214  // Blue
215  //(*ptr)({biHeight-1 - h,w/3,2}) = (int(img[i] & 0xff)) / (255.0);
216  data_ptr[(biHeight-1 - h)*biWidth + w/img_channels + 2*biWidth*biHeight] = (int(img[i + boff] & 0xff)) / (255.0);
217 
218  }
219  }
220 
221  //std::cout << " ptr = " << (*ptr) << std::endl;
222  return ptr;
223  }
224 
229 
230 protected:
231  // Unhide the fields inherited from the template class Layer via "using" statement.
232  using Importer< mic::types::Tensor<eT>, unsigned int >::registerProperty;
233  using Importer< mic::types::Tensor<eT>, unsigned int >::sample_data;
237 
238 private:
239 
243  mic::configuration::Property<std::string> data_filename;
244 
245 };
246 
247 
248 } /* namespace importers */
249 } /* namespace mic */
250 
251 
252 
253 
254 
255 #endif /* BMPIMPORTER_HPP_ */
mic::configuration::Property< std::string > data_filename
mic::types::TensorPtr< float > loadBMP(std::ifstream &file_)
std::vector< size_t > sample_indices
Stores sample indices (sample "positions" in original dataset).
Definition: Batch.hpp:460
Parent class for all data importers.
Definition: Importer.hpp:51
std::vector< std::shared_ptr< mic::types::Tensor< eT > > > sample_data
Stores the data.
Definition: Batch.hpp:454
#define MAKE_TENSOR_PTR(eT,...)
Macro for initialization of tensor pointer.
Definition: TensorTypes.hpp:45
Contains declaration (and definition) of base template class of all data importers.
void setDataFilename(std::string data_filename_)
Definition: BMPImporter.hpp:68
typename std::shared_ptr< mic::types::Tensor< eT > > TensorPtr
Typedef for a shared pointer to template-typed dynamic matrices.
Definition: TensorTypes.hpp:39
std::vector< std::shared_ptr< unsigned int > > sample_labels
Stores labels.
Definition: Batch.hpp:457
virtual void initializePropertyDependentVariables()
Class responsible for importing CIFAR images. Returns a batch of Tensors. Assumes that every image ca...
Definition: BMPImporter.hpp:41
BMPImporter(std::string node_name_="bmp_importer", std::string data_filename_="")
Definition: BMPImporter.hpp:48
Contains declaration of tensor types.