MachineIntelligenceCore:Visualization
WindowRGBTensor.hpp
Go to the documentation of this file.
1 
25 #ifndef WINDOWRGBTENSOR_H_
26 #define WINDOWRGBTENSOR_H_
27 
30 
31 // Dependencies on core types.
32 #include <types/TensorTypes.hpp>
33 
34 namespace mic {
35 namespace opengl {
36 namespace visualization {
37 
42 class RGB {
43 public:
44 
49  Chan_SeparateColor, //< Displays separate channels, colored according to the channel type (R/G/B)
50  Chan_SeparateGrayscale, //< Displays separate channels, all in grayscale.
51  Chan_RGB //< Displays RGB image.
52  };
53 
57  std::string chan2str(ChannelDisplay chan_)
58  {
59  switch(chan_) {
60  case(Chan_SeparateColor):
61  return "Displays separate channels, colored according to the channel type (R/G/B)";
63  return "Displays separate channels, all in grayscale";
64  case(Chan_RGB):
65  return "Displays RGB image";
66  }
67  return "UNDEFINED";
68  }
69 
74  Norm_None //< Displays original image(s), without any normalization (negative values simply won't be visible).
75  //Norm_Positive //< Displays image(s) with channels normalized to <0,1>.
76  };
77 
81  std::string norm2str(Normalization norm_)
82  {
83  switch(norm_) {
84  case(Norm_None):
85  return "Display original image(s), without any normalization";
86  }
87  return "UNDEFINED";
88  }
89 
93  enum Grid {
94  Grid_None, //< No grid
95  Grid_Sample, //< Displays only grid dividing sample cells.
96  Grid_Batch, //< Displays grid dividing samples.
97  Grid_Both //< Displays both sample and batch grids.
98  };
99 
103  std::string grid2str(Grid grid_)
104  {
105  switch(grid_) {
106  case(Grid_None):
107  return "Display no grid";
108  case(Grid_Sample):
109  return "Display only grid dividing sample cells";
110  case(Grid_Batch):
111  return "Display grid dividing samples";
112  case(Grid_Both):
113  return "Display both sample and batch grids";
114  }
115  return "UNDEFINED";
116  }
117 };
118 
124 template <typename eT=float>
125 class WindowRGBTensor: public Window, public RGB {
126 public:
127 
131  WindowRGBTensor(std::string name_ = "WindowRGBTensor",
132  ChannelDisplay channel_display_ = Chan_RGB, Normalization normalization_ = Norm_None, Grid grid_ = Grid_Batch,
133  unsigned int position_x_ = 0, unsigned int position_y_ = 0,
134  unsigned int width_ = 512,unsigned int height_ = 512,
135  bool draw_batch_grid_ = true, bool draw_sample_grid_ = false) :
136  Window(name_, position_x_, position_y_, width_, height_),
137  channel_display(channel_display_),
138  normalization(normalization_ ),
139  grid(grid_)
140  {
141  // Register additional key handler.
142  REGISTER_KEY_HANDLER('c', "c - toggles channel display mode", &WindowRGBTensor<eT>::keyhandlerToggleChannelDisplayMode);
143  REGISTER_KEY_HANDLER('g', "g - toggles grid mode", &WindowRGBTensor<eT>::keyhandlerGridMode);
144 
145  }
146 
150  virtual ~WindowRGBTensor() { }
151 
156  // Enter critical section.
157  APP_DATA_SYNCHRONIZATION_SCOPED_LOCK();
159  LOG(LINFO) << chan2str(channel_display);
160  // End of critical section.
161  }
162 
166  void keyhandlerGridMode(void) {
167  // Enter critical section.
168  APP_DATA_SYNCHRONIZATION_SCOPED_LOCK();
169  grid = (Grid)((grid + 1) % 4);
170  LOG(LINFO) << grid2str(grid);
171  // End of critical section.
172  }
173 
174 
178  void displayHandler(void){
179  LOG(LTRACE) << "WindowRGBTensor::Display handler of window " << glutGetWindow();
180  // Enter critical section.
181  APP_DATA_SYNCHRONIZATION_SCOPED_LOCK();
182 
183  // Clear buffer.
184  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
185  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
186 
187  // Draw batch - vector of 2d matrices.
188  if (batch_data.size() > 0){
189  // Calculate batch "dimensions".
190  size_t batch_width = ceil(sqrt(batch_data.size()));
191  size_t batch_height = ceil((eT)batch_data.size()/batch_width);
192 
193  // Tensor dimensions.
194  size_t height;
195  size_t width;
196  size_t depth;
197 
198  // Opengl scale.
199  eT scale_x, scale_y;
200 
201  // Iterate through batch elements.
202  for (size_t by=0; by < batch_height; by++)
203  for (size_t bx=0; bx < batch_width; bx++) {
204  // Check if we do not excess size.
205  if ((by*batch_width + bx) >= batch_data.size())
206  break;
207 
208  // Get pointer to a given tensor.
209  eT* data_ptr = batch_data[by*batch_width + bx]->data();
210 
211  // Get dimensions.
212  height = batch_data[by*batch_width + bx]->dim(0);
213  width = batch_data[by*batch_width + bx]->dim(1);
214  depth = batch_data[by*batch_width + bx]->dim(2);
215  assert(depth >= 3); // for now: other dimensions will be skipped.
216 
217  // Draw depending on the channel display mode.
218  switch(channel_display) {
219  case ChannelDisplay::Chan_SeparateColor:
220 
221  // Calculate scale.
222  scale_x = (eT)glutGet(GLUT_WINDOW_WIDTH)/(eT)(width * batch_width * 3);
223  scale_y = (eT)glutGet(GLUT_WINDOW_HEIGHT)/(eT)(height * batch_height);
224 
225  // Iterate through matrix elements.
226  for (size_t y = 0; y < height; y++) {
227  for (size_t x = 0; x < width; x++) {
228  // Get value - row-major!
229  eT red = data_ptr[y*width + x]; // first channel
230  eT green = data_ptr[y*width + x + (height*width)];
231  eT blue = data_ptr[y*width + x + 2*(height*width)];
232 
233  // Draw red rectangle - (x, y, height, width, color)!!
234  draw_filled_rectangle(eT(3*bx*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
235  (eT)red,
236  (eT)0.0,
237  (eT)0.0,
238  (eT)1.0f);
239 
240  // Draw green rectangle - (x, y, height, width, color)!!
241  draw_filled_rectangle(eT((3*bx+1)*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
242  (eT)0.0,
243  (eT)green,
244  (eT)0.0,
245  (eT)1.0f);
246 
247  // Draw blue rectangle - (x, y, height, width, color)!!
248  draw_filled_rectangle(eT((3*bx+2)*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
249  (eT)0.0,
250  (eT)0.0,
251  (eT)blue,
252  (eT)1.0f);
253 
254  }//: for
255  }//: for
256 
257  break;
258 
259  case ChannelDisplay::Chan_SeparateGrayscale:
260 
261  // Calculate scale.
262  scale_x = (eT)glutGet(GLUT_WINDOW_WIDTH)/(eT)(width * batch_width * 3);
263  scale_y = (eT)glutGet(GLUT_WINDOW_HEIGHT)/(eT)(height * batch_height);
264 
265  // Iterate through matrix elements.
266  for (size_t y = 0; y < height; y++) {
267  for (size_t x = 0; x < width; x++) {
268  // Get value - row-major!
269  eT red = data_ptr[y*width + x]; // first channel
270  eT green = data_ptr[y*width + x + (height*width)];
271  eT blue = data_ptr[y*width + x + 2*(height*width)];
272 
273  // Draw red rectangle - (x, y, height, width, color)!!
274  draw_filled_rectangle(eT(3*bx*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
275  (eT)red,
276  (eT)red,
277  (eT)red,
278  (eT)1.0f);
279 
280  // Draw green rectangle - (x, y, height, width, color)!!
281  draw_filled_rectangle(eT((3*bx+1)*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
282  (eT)green,
283  (eT)green,
284  (eT)green,
285  (eT)1.0f);
286 
287  // Draw blue rectangle - (x, y, height, width, color)!!
288  draw_filled_rectangle(eT((3*bx+2)*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
289  (eT)blue,
290  (eT)blue,
291  (eT)blue,
292  (eT)1.0f);
293 
294  }//: for
295  }//: for
296 
297  break;
298  // RGB is default.
299  case ChannelDisplay::Chan_RGB:
300  default:
301  // Calculate scale.
302  scale_x = (eT)glutGet(GLUT_WINDOW_WIDTH)/(eT)(width * batch_width);
303  scale_y = (eT)glutGet(GLUT_WINDOW_HEIGHT)/(eT)(height * batch_height);
304 
305  // Iterate through matrix elements.
306  for (size_t y = 0; y < height; y++) {
307  for (size_t x = 0; x < width; x++) {
308  // Get value - row-major!
309  eT red = data_ptr[y*width + x]; // first channel
310  eT green = data_ptr[y*width + x + (height*width)];
311  eT blue = data_ptr[y*width + x + 2*(height*width)];
312 
313  // Draw rectangle - (x, y, height, width, color)!!
314  draw_filled_rectangle(eT(bx*width+x) * scale_x, eT(by*height+y) * scale_y, scale_y, scale_x,
315  (eT)red,
316  (eT)green,
317  (eT)blue,
318  (eT)1.0f);
319 
320  }//: for
321  }//: for
322 
323  break;
324  }//: switch
325 
326 
327  }//: for images in batch
328 
329  // Draw grids dividing the cells and batch samples.
330  switch(grid) {
331  case Grid::Grid_Sample :
332  // Draw depending on the channel display mode.
333  switch(channel_display) {
334  case ChannelDisplay::Chan_SeparateColor:
335  case ChannelDisplay::Chan_SeparateGrayscale:
336  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width * width * 3, batch_height * height);
337  break;
338  default:
339  case ChannelDisplay::Chan_RGB:
340  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width * width, batch_height * height);
341  }
342  break;
343  case Grid::Grid_Batch:
344  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width, batch_height, 4.0);
345  break;
346  case Grid::Grid_Both:
347  // Draw depending on the channel display mode.
348  switch(channel_display) {
349  case ChannelDisplay::Chan_SeparateColor:
350  case ChannelDisplay::Chan_SeparateGrayscale:
351  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width * width * 3, batch_height * height);
352  break;
353  default:
354  case ChannelDisplay::Chan_RGB:
355  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width * width, batch_height * height);
356  }
357  draw_grid(0.3f, 0.8f, 0.3f, 0.3f, batch_width, batch_height, 4.0);
358  break;
359  // None is default.
360  case Grid::Grid_None:
361  default:
362  break;
363  }//: switch
364  }//: if !null
365 
366  // Swap buffers.
367  glutSwapBuffers();
368 
369  // End of critical section.
370  }
371 
376  void setSampleSynchronized(mic::types::TensorPtr<eT> sample_ptr_) {
377  // Enter critical section.
378  APP_DATA_SYNCHRONIZATION_SCOPED_LOCK();
379 
380  // Clear - just in case.
381  batch_data.clear();
382  // Add sample.
383  batch_data.push_back(sample_ptr_);
384 
385  // End of critical section.
386  }
387 
392  void setSampleUnsynchronized(mic::types::TensorPtr<eT> sample_ptr_) {
393  // Clear - just in case.
394  batch_data.clear();
395  // Add sample.
396  batch_data.push_back(sample_ptr_);
397  }
398 
403  void setBatchSynchronized(std::vector <mic::types::TensorPtr<eT> > & batch_data_) {
404  // Enter critical section.
405  APP_DATA_SYNCHRONIZATION_SCOPED_LOCK();
406 
407  batch_data = batch_data_;
408 
409  // End of critical section.
410  }
411 
416  void setBatchUnsynchronized(std::vector <mic::types::TensorPtr<eT> > & batch_data_) {
417  batch_data = batch_data_;
418  }
419 
420 
421 private:
422 
426  std::vector <mic::types::TensorPtr<eT> > batch_data;
427 
430 
433 
436 };
437 
438 } /* namespace visualization */
439 } /* namespace opengl */
440 } /* namespace mic */
441 
442 #endif /* WINDOWRGBTENSOR_H_ */
std::string norm2str(Normalization norm_)
std::vector< mic::types::TensorPtr< eT > > batch_data
void draw_filled_rectangle(float x, float y, float h, float w, float r, float g, float b, float a)
std::string chan2str(ChannelDisplay chan_)
void setBatchUnsynchronized(std::vector< mic::types::TensorPtr< eT > > &batch_data_)
ChannelDisplay channel_display
Grid display mode.
void setSampleSynchronized(mic::types::TensorPtr< eT > sample_ptr_)
void setSampleUnsynchronized(mic::types::TensorPtr< eT > sample_ptr_)
WindowRGBTensor(std::string name_="WindowRGBTensor", ChannelDisplay channel_display_=Chan_RGB, Normalization normalization_=Norm_None, Grid grid_=Grid_Batch, unsigned int position_x_=0, unsigned int position_y_=0, unsigned int width_=512, unsigned int height_=512, bool draw_batch_grid_=true, bool draw_sample_grid_=false)
Normalization normalization
Normalization mode.
Contains declaration of parent class of all OpenGL-based windows.
void setBatchSynchronized(std::vector< mic::types::TensorPtr< eT > > &batch_data_)
std::string grid2str(Grid grid_)
Parent class of all OpenGL-based windows (abstract).
Definition: Window.hpp:51
OpenGL-based window responsible for displaying RGB (three channel) batch in a window.
void draw_grid(float r, float g, float b, float a, float cells_h, float cells_v, float line_width_=1.0)
Declaration of WindowManager class along with a bunch of helpful types and macros.
Class containing enumerators used in windows displaying RGB images (tensors).