X-Boost  2.3.8
SourceDataSet.h
Go to the documentation of this file.
1 /* XBoost: Ada-Boost and Friends on Haar/ICF/HOG Features, Library and ToolBox
2  *
3  * Copyright (c) 2008-2014 Paolo Medici <medici@ce.unipr.it>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef _SOURCE_DATA_SET_H
22 #define _SOURCE_DATA_SET_H
23 
24 
25 #include "IO/pnmio.h"
26 #include "IO/datasetin.h"
27 #include "Image.h"
28 #include "DataSet.h"
29 #include "Utility/ImageUtils.h"
30 
31 #include <stdio.h> // sprintf
32 #include <stdlib.h> // rand
33 
45 template<class TPreprocessorType, class Aggregator>
46 class SourceDataSet: public TPreprocessorType, public DataSet<Aggregator> {
47 public:
48 
51 
52  DECLARE_AGGREGATOR
53 
54 private:
56  bool m_initialized;
57 
59  bool m_export_data_set;
60 
62  std::string m_export_path;
63 
64 public:
65 
66  SourceDataSet() : m_initialized(false), m_export_data_set(false) { }
67 
69  bool ImportImage(const ImageHandle & image, int category);
70 
72  void SetExportFolder(const std::string & folder) {
73  m_export_data_set = true;
74  m_export_path = folder;
75  }
76 };
77 
79 
80 extern int frameidx;
81 
82 // Import a GrayScale Image
83 template<class TPreprocessorType, class Aggregator>
85 {
86  typename TPreprocessorType::ReturnType data; // processed data (pair of <DATA, PARAMS> )
87 
88  if(m_export_data_set)
89  {
90  char buffer[256];
91  int count = this->templates.size();
92  if(category == 1)
93  sprintf(buffer, "%s/P%06u_%u.pgm", m_export_path.c_str(), count, frameidx);
94  else
95  sprintf(buffer, "%s/N%06u_%u.pgm", m_export_path.c_str(), count, frameidx);
96  pnm_write(image, buffer);
97  }
98 
99  // il proceprocessor converte da image a ReturnType (un pair composto dal dato e dalla geometria)
100  if(image.bpp == 1)
101  {
102  TPreprocessorType::Process(data, (unsigned char *) image.data, image.width, image.height, image.stride );
103  }
104  else if(image.bpp == 2)
105  {
106  TPreprocessorType::Process(data, (unsigned short *) image.data, image.width, image.height, image.stride );
107  }
108  else
109  {
110  std::cerr << "Invalid bpp = " << image.bpp << " for this data set" << std::endl;
111  return false;
112  }
113 
114  if(!m_initialized)
115  {
116  // set the parameters on DataSet
117  this->SetParams(data.second);
118  m_initialized = true;
119  }
120  else
121  {
122  // verificare che la geometria sia corretta
123  if(!( static_cast<const ParamType &>(*this) == data.second))
124  {
125  std::cerr << "invalid geometry" << std::endl;
126  return false;
127  }
128  }
129 
130  // import the data inside the DataSet
131  this->Import(data.first, category);
132  return true;
133 }
134 
137 template<class DataSetType>
138 bool RandomExtract(DataSetType & set, const ImageHandle & img, const size & set_geometry, int nRand, const std::vector<datasetobject> & object)
139 {
140  if(img.width < set_geometry.width || img.height < set_geometry.height)
141  {
142  std::cerr << "the image is too small to be used during negative random extraction" << std::endl;
143  return false;
144  }
145 
146  // for any candidate in the set
147  for(int k=0; k<nRand; ++k)
148  {
149  int x0 = rand() % (img.width - set_geometry.width);
150  int y0 = rand() % (img.height - set_geometry.height);
151  rect roi(x0, y0, x0 + set_geometry.width, y0 + set_geometry.height);
152 
153  bool collision = false;
154  // Check Collision
155  for(std::vector<datasetobject>::const_iterator i = object.begin(); i != object.end(); ++i)
156  if(overlap(roi, i->roi))
157  {
158  collision = true;
159  break;
160  }
161 
162  if(!collision)
163  {
164  if(!set.ImportImage(img.crop(roi), -1)) // only negative
165  {
166  std::cerr << "Failed to import pattern";
167  return false;
168  }
169  }
170  }
171  return true;
172 }
173 
175 // struct LoadSetParams {
176 // bool sz_valid;
177 // size sz;
178 // int nRand;
179 // float scale_factor;
180 // };
181 
185 template<class DataSetType>
186 bool LoadSet(DataSetType & set, datasetin & in, const size & sz, int nRand)
187 {
188  datasetitem item;
189  size set_geometry = sz; //
190 
191  if(set_geometry.width != 0 || set_geometry.height!=0)
192  std::cout << "LoadSet with geometry " << set_geometry.width << 'x' << set_geometry.height << std::endl;
193 
194  // iterate on input data
195  while(in.next(item))
196  {
197 // bool have_negative = false;
198  Image img;
199  if(!pnm_load(item.filename.c_str(), img))
200  {
201  std::cout << "Warn: \'" << item.filename << "' failed to load: skip." << std::endl;
202  }
203  else
204  {
205  // for any candidate in the set (positive/negative)
206  for(std::vector<datasetobject>::const_iterator i = item.object.begin(); i != item.object.end(); ++i)
207  if(i->category != 0) // DO NOT CARE
208  {
209  rect roi = i->roi;
210 
211  // whole image ROI
212  if(roi.x0 == 0 && roi.y0 == 0 && roi.x1 == 0 && roi.y1 == 0)
213  {
214  roi.x1 = img.width;
215  roi.y1 = img.height;
216  }
217 
218  if(roi.x0 < 0 || roi.y0 < 0 || roi.x1 > (int) img.width || roi.y1 > (int) img.height)
219  {
220  std::cout << "Warn: ROI #" << (i - item.object.begin()) << " is out of image " << item.filename << std::endl;
221  }
222  else
223  {
224 
225  if(set_geometry.width == 0 && set_geometry.height==0)
226  {
227  set_geometry.width = roi.width();
228  set_geometry.height = roi.height();
229  std::cout << "Geometry: " << set_geometry.width << 'x' << set_geometry.height << std::endl;
230  }
231 
232  if(set_geometry == roi.extension()) // se sono uguali viene fatto un Crop
233  {
234  if(!set.ImportImage(img.crop(roi), i->category))
235  std::cerr << "Failed to import image " << item.filename << std::endl;
236  }
237  else
238  {
239  // resize
240  Image img2;
241 // std::cout << item.filename << " convert " << roi.width() << 'x' << roi.height() << " to " << set_geometry.width << 'x' << set_geometry.height << '\n';
242  img2.alloc(set_geometry.width, set_geometry.height, 1);
243  Resample(img2, img.crop(roi), rect(0,0, roi.width(), roi.height()));
244  set.ImportImage(img2, i->category);
245  }
246 
247  }
248 
249  }
250 
251  // se e' un file da estrazione automatica di negativi, li usa
252  if(item.auto_negative && (nRand>0))
253  {
254  if(set_geometry.width == 0 || set_geometry.height == 0)
255  {
256  std::cerr << "Error: Invalid geometry for random sample extraction. Check -r <w> <h> option." << std::endl;
257  }
258  else
259  {
260  std::cout << "Extract random from " << item.filename << " ID:" << frameidx << std::endl;
261  std::vector<datasetobject> list = item.object;
262 
263  // for all octaves:
264  for(;;) {
265 
266  RandomExtract(set, img, set_geometry, nRand, list);
267 
268  if(img.width > 2 * set_geometry.width && img.height > 2 * set_geometry.height)
269  {
270  Image out;
271  out.alloc(img.width/2, img.height/2, 1);
272  Downsample2X(out, img);
273 
274  for(std::vector<datasetobject>::iterator i = list.begin(); i != list.end(); ++i)
275  {
276  i->roi.x0 /= 2;
277  i->roi.y0 /= 2;
278  i->roi.x1 = (i->roi.x1+1)/2;
279  i->roi.y1 = (i->roi.y1+1)/2;
280  }
281 
282  std::swap(img, out);
283  }
284  else
285  break;
286  }
287 
288  }
289 
290  frameidx++;
291  }
292 
293  }
294 
295  }
296 
297  frameidx = 0;
298  return true;
299 }
300 
301 #endif
DataSetHandle< Aggregator > DataSetType
the dataset (contains DataType plus additional data)
Definition: SourceDataSet.h:50
int frameidx
a counter, used for debug
bool LoadSet(DataSetType &set, datasetin &in, const size &sz, int nRand)
some parameters used in LoadSet
Definition: SourceDataSet.h:186
bool RandomExtract(DataSetType &set, const ImageHandle &img, const size &set_geometry, int nRand, const std::vector< datasetobject > &object)
Definition: SourceDataSet.h:138
bool pnm_load(const char *file, Image &out)
PNM files I/O.
unsigned int bpp
byte per pixel (1 for grayscale image, 2 for 16bit greyscale image, 3 for RGB/YUV/etc color image) ...
Definition: Image.h:37
a virtual pure pattern list reader
Definition: datasetin.h:56
Definition: Image.h:35
a structure to hold image data (memory)
Definition: Image.h:74
ImageHandle crop(int x0, int y0, int x1, int y1) const
return a subpart of the image (without copy)
Definition: Image.h:47
void Downsample2X(ImageHandle &out, const ImageHandle &in)
Downsample (a factor of 2) the whole image.
bool pnm_write(const ImageHandle &in, const char *file)
Definition: DataSet.h:33
bool ImportImage(const ImageHandle &image, int category)
Import an Image and transform it using "Preprocessor".
Definition: SourceDataSet.h:84
Definition: DataSet.h:50
void SetExportFolder(const std::string &folder)
Set the folder where store pattern generated in the dataset.
Definition: SourceDataSet.h:72
method to process image
image/size TODO namespace
Definition: Types.h:39
void Resample(ImageHandle &out, const ImageHandle &in, const rect &area)
Crop and Resample an Image using IntegralImage algorithm.
Definition: SourceDataSet.h:46
long stride
line stride, the delta offset, in bytes, between two different scanline
Definition: Image.h:41
method to hold an image
an item used for positive
Definition: datasetin.h:44
unsigned int width
image geometry
Definition: Image.h:39
std::vector< datasetobject > object
List of object.
Definition: datasetin.h:52
bool overlap(const rect &a, const rect &b)
test if 2 rect are overlapped
a rectangle structure
Definition: Types.h:55
virtual class to import images
declare a DataSet
std::string filename
filename
Definition: datasetin.h:46
unsigned char * data
initial address of the first pixel. It must be cast to correct format (uint8, uint16, rgb, etc etc)
Definition: Image.h:43
bool auto_negative
if the rest of the blob can be used as source for negative
Definition: datasetin.h:50
void alloc(unsigned int w, unsigned int h, unsigned int b)
reserve memory for the image
Definition: Image.h:98