Structural deformable models
deform.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * *
3  * deformable models *
4  * *
5  ******************************************************************************/
6 //-- fox system setup
7 #include "deform.h"
8 #include <fx3d.h>
9 #include <fxkeys.h>
10 #include <string.h>
11 #include <iostream>
12 #include <time.h>
13 #include "glutils.h"
14 
15 using namespace std;
16 
17 #ifdef WIN32
18 #define SHIFT_CANVAS_ORIGIN
19 #endif
20 
21 #define STATUSTXTLEN 2048
22 const FXuint TIMER_INTERVAL = 50;
23 
24 // Patterns
25 const FXString patterns =
26  "All Files (*)\n"
27  "GIF Image (*.gif)\n"
28  "BMP Image (*.bmp)\n"
29  "XPM Image (*.xpm)\n"
30  "PCX Image (*.pcx)\n"
31  "RGB Image (*.rgb)\n"
32 //#ifdef HAVE_PNG_H
33  "PNG Image (*.png)\n"
34 //#endif
35 //#ifdef HAVE_JPEG_H
36  "JPEG Image (*.jpg)\n"
37 //#endif
38  "TARGA Image (*.tga)\n"
39 //#ifdef HAVE_JPEG_H
40  "TIFF Image (*.tif)\n"
41 //#endif
42  ;
43 
44 // Message Map
45 FXDEFMAP(ImageWindow) ImageWindowMap[]={
46 
47  //____Message_Type______________ID_______________Message_Handler___
48  //FXMAPFUNC(SEL_PAINT, ImageWindow::ID_CANVAS, ImageWindow::onCanvasRepaint),
49  FXMAPFUNC(SEL_LEFTBUTTONPRESS, ImageWindow::ID_CANVAS, ImageWindow::onLeftMouseClick),
50  FXMAPFUNC(SEL_RIGHTBUTTONPRESS, ImageWindow::ID_CANVAS,
52  FXMAPFUNC(SEL_MOTION, ImageWindow::ID_CANVAS, ImageWindow::onMouseMove),
53  FXMAPFUNC(SEL_KEYPRESS,0,ImageWindow::onKeyPress),
54  //FXMAPFUNC(SEL_KEYRELEASE,0,ImageWindow::onKeyRelease),
55  FXMAPFUNC(SEL_COMMAND, ImageWindow::ID_LOAD, ImageWindow::onLoadImage),
57  FXMAPFUNC(SEL_PAINT, ImageWindow::ID_CANVAS, ImageWindow::onExpose),
58  FXMAPFUNC(SEL_CONFIGURE, ImageWindow::ID_CANVAS, ImageWindow::onConfigure),
59  FXMAPFUNC(SEL_TIMEOUT, ImageWindow::ID_TIMEOUT, ImageWindow::onTimeout),
60  FXMAPFUNC(SEL_COMMAND, ImageWindow::ID_OPENGL, ImageWindow::onCmdOpenGL),
61 };
62 
63 
64 
65 // Macro for the App class hierarchy implementation
66 FXIMPLEMENT(ImageWindow,FXMainWindow,ImageWindowMap,ARRAYNUMBER(ImageWindowMap))
67 
68 bool setTitle(const std::string& title) {
69  ImageWindow *mw = dynamic_cast<ImageWindow*>
70  (FXApp::instance()->getRootWindow());
71  if(mw) {
72  mw->setTitle(title.c_str());
73  return true;
74  } else return false;
75 }
76 
77 bool setStatusText(const std::string& stext) {
78  ImageWindow *mw = dynamic_cast<ImageWindow*>
79  (FXApp::instance()->getRootWindow());
80  if(mw) {
81  mw->setStatusText(stext.c_str());
82  return true;
83  } else return false;
84 }
85 
86 
87 // Construct ImageWindow
88 ImageWindow::ImageWindow(FXApp* a):FXMainWindow(a,"Deformable Model Segmentation",NULL,NULL,DECOR_ALL,0,0,800,600){
89  FXVerticalFrame *canvasFrame;
90  FXVerticalFrame *buttonFrame;
91  FXHorizontalFrame *contents;
92 
93  contents=new FXHorizontalFrame(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0);
94 
95  canvasFrame=new FXVerticalFrame(contents,FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,10,10,10,10);
96 
97  // A Visual to drag OpenGL
98  glvisual=new FXGLVisual(getApp(),VISUAL_DOUBLEBUFFER);
99 
100  // Drawing glcanvas
101  glcanvas=new FXGLCanvas(canvasFrame,glvisual,this,ID_CANVAS,LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT);
102 
103  // RIGHT pane for the buttons
104  buttonFrame=new FXVerticalFrame(contents,FRAME_SUNKEN|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,10,10,10,10);
105 
106  new FXButton(buttonFrame,"L&oad Image\tSelect Image to load",NULL, this, ID_LOAD,FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,10,10,5,5);
107 // new FXButton(buttonFrame,"&Process\tPerform some wicked image processsing",NULL,
108 // this, ID_PROCESS,
109 // FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,
110 // 0,0,0,0,10,10,5,5);
111  // SensorEditor button
112  new FXButton(buttonFrame,"Edit &Sensors\tEdit the sensor collection",NULL,this,ID_EDSENS,FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,10,10,5,5);
113 
114  // Exit button
115  new FXButton(buttonFrame,"E&xit\tQuit ImageApp",NULL,getApp(),FXApp::ID_QUIT,FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,10,10,5,5);
116  FXStatusBar *sbar = new FXStatusBar(canvasFrame,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
117  m_Statusline = sbar->getStatusLine();
118 
119  m_SensorDlg = new SensorDialog(getApp(), this,
120  (SensorCollection&)m_Brain.getSensors());
121  // Result image*/
122 
123  filename = "untitled";
124  directory = ".";
125 
126  getApp()->addTimeout(this,ID_TIMEOUT,TIMER_INTERVAL);
127 // if(!m_Brain.loadModel("shape.dm"))
128 // setStatusText("Error loading geometry.");
129  //if(!m_Brain.load("default.brain"))
130 // setStatusText("Error loading brain info [default.brain].");
131  m_Brain.toggleUpdateForAll();
132  m_BrainStarted = false;
133 }
134 
135 // Destroy ImageWindow
137  getApp()->removeTimeout(this,ID_TIMEOUT);
138 }
139 
140 
141 // Create and initialize
142 void ImageWindow::create(){
143 
144  // Create the windows
145  FXMainWindow::create();
146 
147  if(filename!="untitled"){
148  setStatusText((FXString("trying to load: ")+filename).text());
149  if(!m_Brain.load(filename.text())) {
150  setStatusText((FXString("error loading ")+filename).text());
151  } else setStatusText("");
152  } else if(!m_Brain.load("default.brain"))
153  setStatusText("Error loading brain info [default.brain].");
154  m_SensorDlg->updateStrings();
155 
156  // Make it appear
157  show(PLACEMENT_SCREEN);
158 }
159 
160 // Handle the clear message
161 long ImageWindow::onCanvasRepaint(FXObject*,FXSelector,void* ptr){
162 
163 // cerr << "onCanvasRepaint: ..."<<endl;
164 // FXDCWindow dc(glcanvas);
165 // // Point pofs(glcanvas->getXPosition(), glcanvas->getYPosition());
166 
167 // dc.setForeground(FXRGB(0,255,0));
168 // dc.drawLine(10,10,100,100);
169  return 1;
170 }
171 
172 
173 // Widget has been resized
174 long ImageWindow::onConfigure(FXObject*,FXSelector,void*){
175  if(glcanvas->makeCurrent()){
176  glEnable(GL_BLEND);
177  //glEnable(GL_SMOOTH);
178  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
179  glDisable(GL_DITHER);
180  glViewport(0,0,glcanvas->getWidth(),glcanvas->getHeight());
181  glcanvas->makeNonCurrent();
182  }
183  return 1;
184 }
185 
186 
187 
188 // Widget needs repainting
189 long ImageWindow::onExpose(FXObject*,FXSelector,void*){
190  drawScene();
191  return 1;
192 }
193 
194 // Draw the GL scene
196  GLdouble width = glcanvas->getWidth();
197  GLdouble height = glcanvas->getHeight();
198  //GLdouble aspect = height>0 ? width/height : 1.0;
199 
200  // Make context current
201  glcanvas->makeCurrent();
202 
203  //glViewport(0,0,glcanvas->getWidth(),glcanvas->getHeight());
204 
205  glClearColor(0.0,0.0,0.0,1.0);
206  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
207 
208  glMatrixMode(GL_MODELVIEW);
209  glLoadIdentity();
210  glMatrixMode(GL_PROJECTION);
211  glLoadIdentity();
212  if(m_Brain.getData().initialized()) {
213  GLint datwidth = m_Brain.getData().getDim1Size();
214  GLint datheight = m_Brain.getData().getDim2Size();
215 // glPixelStorei(GL_UNPACK_ROW_LENGTH, datwidth);
216 // glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
217  GLfloat xscale = ((float)width)/datwidth;
218  GLfloat yscale = ((float)height)/datheight;
219  m_XYScale = xscale<yscale?xscale:yscale;
220  GLfloat swidth = width/m_XYScale;
221  GLfloat sheight = height/m_XYScale;
222  glOrtho(0,swidth,
223  sheight,0,
224  -1000,1000);
225  glEnable(GL_TEXTURE_2D);
226  glColor3f(1.f, 1.f, 1.f);
227  if(m_ScreenImg.getSize()) {
228  if(m_RefreshScreenImg || !m_GLScreenImg) {
229  m_GLScreenImg.setImage(m_ScreenImg);
230  m_RefreshScreenImg = false;
231  }
232  m_GLScreenImg.draw(0,0);
233  //Dataset::drawImage(m_ScreenImg,0,datheight,m_XYScale,m_XYScale);
234  } else
235  m_Brain.getData().draw(0,0);
236  glDisable(GL_TEXTURE_2D);
237  }
238 
239  m_Brain.drawAllModels();
240 
241  // Swap if it is double-buffered
242  if(glvisual->isDoubleBuffer()){
243  glcanvas->swapBuffers();
244  }
245 
246  // Make context non-current
247  glcanvas->makeNonCurrent();
248 
249  if(m_BrainStarted && m_Brain.isDone()) {
250  setStatusText("Done.");
251  m_BrainStarted = false;
252  }
253 }
254 
255 
256 // Pop a dialog showing OpenGL properties
257 long ImageWindow::onCmdOpenGL(FXObject*,FXSelector,void*){
258  glcanvas->makeCurrent();
259 // SettingsDialog sd((FXWindow*)this,glvisual);
260  glcanvas->makeNonCurrent();
261  //sd.execute();
262  return 1;
263 }
264 
265 long ImageWindow::onToggleSensorDlg(FXObject*,FXSelector,void*){
266  if(m_SensorDlg->shown()) m_SensorDlg->hide();
267  else m_SensorDlg->show();
268  return 1;
269 }
270 
271 // Open image
272 long ImageWindow::onLoadImage(FXObject*,FXSelector,void*){
273  FXFileDialog open(this,"Load Image (BMP,GIF,TGA)");
274 
275  open.setDirectory(directory);
276  open.setFilename(filename);
277  open.setPatternList(patterns);
278  if(open.execute()){
279  filename = open.getFilename();
280  directory = open.getDirectory();
281  m_ScreenImg.setSize(0,0);
282  setStatusText((FXString("trying to load: ")+filename).text());
283  if(!m_Brain.loadData(filename.text()))
284  setStatusText(("Error loading file "+filename).text());
285  }
286  return 0;
287 }
288 
289 // Key Press
290 long ImageWindow::onKeyPress(FXObject* obj,FXSelector sel,void* ptr){
291  FXEvent* event=(FXEvent*)ptr;
292  if(target && target->handle(this,MKUINT(message,SEL_KEYPRESS),ptr)) return 1;
293  int _x,_y,mx,my;
294  _x=m_Brain.getData().getDim1Size();
295  _y=m_Brain.getData().getDim2Size();
296  mx=event->win_x;
297  my=event->win_y;
298 #ifdef SHIFT_CANVAS_ORIGIN
299  mx-=glcanvas->getX();
300  my-=glcanvas->getY();
301 #endif
302  mx=(int)(mx/m_XYScale);
303  my=(int)(my/m_XYScale);
304  if(event->code>=KEY_F5 && event->code<=KEY_F10)
305  {
306  static int sido=0;
307  int kid = event->code - KEY_F5;
308  switch(kid) {
309  case 0: sido=0; break;
310  case 1: sido--; break;
311  case 2: break;
312  case 3: sido++; break;
313  }
314  sido = selectSensor(sido);
315  return 1;
316  }
317  if( mx < _x && my < _y ) {
318  int what = event->code;
319  if(what == KEY_F3) m_BrainStarted = !m_BrainStarted; // if F3
320  if(m_Brain.triggerTest(mx, my, what)) return 1;
321  }
322  return FXMainWindow::onKeyPress(obj,sel,ptr);
323 }
324 
326 {
327  vuLock glock(m_Brain.getGeomMutex());
328  SensorCollection &sensors = m_Brain.getSensors();
329  sensor_ptr ss = NULL;
330  if((int)sensors.size()<=sido) sido=0;
331  if(sido<0) sido=sensors.size()-1;
332  int sid = sido;
333  for(SensorCollection::iterator s=sensors.begin();
334  s!=sensors.end();s++,sid--) {
335  if(!sid) {
336  ss = s->second;
337  break;
338  }
339  }
340  if(!ss || !sido) {
341  setStatusText("Showing original image.");
342  m_ScreenImg.setSize(0,0);
343  ((SensorCollection&)sensors).selectSensor("d0");
344  } else {
345  if(!ss->isUpdate(Sensor::UPD_MINMAX)) {
346  ss->enableUpdate(Sensor::UPD_MINMAX);
347  ss->setModified(Sensor::UPD_MINMAX);
348  }
349  Image<float> simg(ss->createSensorImage());
350  simg.unsetNAN(0);
351  float imax=ss->getMax(); //simg.findMax();
352  float imin=ss->getMin(); //simg.findMin();
353  //simg+=-imin;
354  //simg*=(255/(imax-imin));
355  simg*=255;
356  m_ScreenImg.convertFrom(simg);
357  m_RefreshScreenImg = true;
358  //m_ScreenImg.writePPM("sensor.ppm");
359  //m_ScreenImg = m_ScreenImg.mirror(false, true);
360 
361  char msg[1024];
362  sprintf(msg,"Showing sensor [%s] (min=%.4f max=%.4f).",
363  ss->getID().c_str(),imin,imax);
364  setStatusText(msg);
365  ((SensorCollection&)sensors).selectSensor(ss->getID());
366  }
367  return sido;
368 }
369 
370 // Key Release
371 long ImageWindow::onKeyRelease(FXObject*,FXSelector,void* ptr){
372 /*
373  FXEvent* event=(FXEvent*)ptr;
374  FXint index=current;
375  flags&=~FLAG_TIP;
376  if(!isEnabled()) return 0;
377  if(index<0) index=0;
378  switch(event->code){
379  case KEY_Space:
380  //blubb
381  }
382 */
383  return 0;
384 }
385 
386 long ImageWindow::onLeftMouseClick(FXObject*,FXSelector,void* ptr){
387 
388  FXEvent *event=(FXEvent*)ptr;
389  FXint _x, _y, mx, my;
390 
391  Point pofs(glcanvas->getX(), glcanvas->getY());
392  _x=m_Brain.getData().getDim1Size();
393  _y=m_Brain.getData().getDim2Size();
394  mx=event->win_x;
395  my=event->win_y;
396 // #ifdef SHIFT_CANVAS_ORIGIN
397 // mx-=glcanvas->getX();
398 // my-=glcanvas->getY();
399 // #endif
400  mx=(int)(mx/m_XYScale);
401  my=(int)(my/m_XYScale);
402  if( mx < _x && my < _y){
403  m_Brain.triggerTest((int)(mx),
404  (int)(my),KEY_Control_L);
405  }
406  return 1;
407 }
408 
409 long ImageWindow::onRightMouseClick(FXObject*,FXSelector,void* ptr){
410 
411  FXEvent *event=(FXEvent*)ptr;
412  FXint _x, _y, mx, my;
413 
414  Point pofs(glcanvas->getX(), glcanvas->getY());
415  _x=m_Brain.getData().getDim1Size();
416  _y=m_Brain.getData().getDim2Size();
417  mx=event->win_x;
418  my=event->win_y;
419 // #ifdef SHIFT_CANVAS_ORIGIN
420 // mx-=glcanvas->getX();
421 // my-=glcanvas->getY();
422 // #endif
423  mx=(int)(mx/m_XYScale);
424  my=(int)(my/m_XYScale);
425  if( mx < _x && my < _y){
426  m_Brain.triggerTest((int)(mx),
427  (int)(my), KEY_P);
428  }
429  return 1;
430 }
431 
432 long ImageWindow::onMouseMove(FXObject*,FXSelector,void* ptr){
433 
434  FXEvent *event=(FXEvent*)ptr;
435  FXint _x, _y, mx, my;
436 
437  Point pofs(glcanvas->getX(), glcanvas->getY());
438  _x=m_Brain.getData().getDim1Size();
439  _y=m_Brain.getData().getDim2Size();
440  mx=event->win_x;
441  my=event->win_y;
442 // #ifdef SHIFT_CANVAS_ORIGIN
443 // mx-=glcanvas->getX();
444 // my-=glcanvas->getY();
445 // #endif
446  mx=(int)(mx/m_XYScale);
447  my=(int)(my/m_XYScale);
448  if( mx < _x && my < _y){
449  m_Brain.triggerTest((int)(mx),
450  (int)(my),KEY_H);
451  }
452  return 1;
453 }
454 
455 // Rotate the boxes when a timer message is received
456 long ImageWindow::onTimeout(FXObject*,FXSelector,void*){
457  drawScene();
458  getApp()->addTimeout(this,ID_TIMEOUT,TIMER_INTERVAL);
459  return 1;
460 }
461 
462 void ImageWindow::setStatusText(const char* msg, bool append)
463 {
464  if(!append)
465  m_Statusline->setNormalText(msg);
466  else
467  m_Statusline->setNormalText(m_Statusline->getNormalText()+FXString(msg));
468 }
469 
470 FXbool ImageWindow::cmdline(int argc, char ** argv){
471 
472  if(argc >= 2) filename=argv[1];
473  if(argc >= 3) savefilename=argv[2];
474 
475  return TRUE;
476 }
477 
478 // Here we begin
479 int main(int argc,char *argv[]){
480 //#define REDIRECT_STDOUT
481 #ifdef REDIRECT_STDOUT
482  ofstream logfile("output.log");
483  cout.rdbuf(logfile.rdbuf());
484  cerr.rdbuf(logfile.rdbuf());
485 #endif
486  // Make application
487  FXApp application("Deformable Model Segmentation","FoxText");
488 
489  // Start app
490  application.init(argc,argv);
491 
492  // Make window
493  ImageWindow *iw = new ImageWindow(&application);
494  iw->cmdline(argc,argv);
495 
496  glutInit(&argc,argv);
497 
498  // Create the application's windows
499  application.create();
500 
501  // Run the application
502  return application.run();
503 }
504 
505 int gethostname(char*,int)
506 {
507  return 0;
508 }
509 
510 /* emacs layout configuration
511  ;;; Local Variables: ***
512  ;;; tab-width: 4 ***
513  ;;; End: ***
514 */
int gethostname(char *, int)
Definition: deform.cpp:505
#define NULL
Definition: simpletypes.h:9
int selectSensor(int sido)
Definition: deform.cpp:325
long onTimeout(FXObject *, FXSelector, void *)
Definition: deform.cpp:456
FXbool cmdline(int argc, char **argv)
Definition: browser.cpp:671
bool setTitle(const std::string &title)
Definition: deform.cpp:68
const FXString patterns
Definition: deform.cpp:25
STL namespace.
long onMouseMove(FXObject *, FXSelector, void *)
Definition: deform.cpp:432
std::shared_ptr< Sensor > sensor_ptr
Definition: types_fwd.h:15
long onKeyPress(FXObject *, FXSelector, void *ptr)
Definition: browser.cpp:415
Image< T > & convertFrom(const Image< S > &rhs)
Definition: Image.h:91
long onLoadImage(FXObject *, FXSelector, void *)
Definition: browser.cpp:370
long onLeftMouseClick(FXObject *, FXSelector, void *)
Definition: browser.cpp:613
long onConfigure(FXObject *, FXSelector, void *)
Definition: browser.cpp:292
bool setStatusText(const std::string &stext)
Definition: deform.cpp:77
FXIMPLEMENT(SensorDialog, FXDialogBox, SensorDialogMap, ARRAYNUMBER(SensorDialogMap)) SensorDialog
Definition: sensordlg.cpp:18
void setStatusText(const char *msg, bool append=false)
Definition: browser.cpp:663
virtual ~ImageWindow()
Definition: browser.cpp:219
FXDEFMAP(ImageWindow) ImageWindowMap[]
long onRightMouseClick(FXObject *, FXSelector, void *)
Definition: browser.cpp:635
long onToggleSensorDlg(FXObject *, FXSelector, void *)
Definition: deform.cpp:265
long onKeyRelease(FXObject *, FXSelector, void *ptr)
Definition: browser.cpp:598
long onCanvasRepaint(FXObject *, FXSelector, void *)
Definition: browser.cpp:276
long onCmdOpenGL(FXObject *, FXSelector, void *)
Definition: browser.cpp:361
Definition: Point.h:16
virtual void create()
Definition: browser.cpp:233
long onExpose(FXObject *, FXSelector, void *)
Definition: browser.cpp:303
void drawScene()
Definition: browser.cpp:309
const FXuint TIMER_INTERVAL
Definition: deform.cpp:22
Image< T > & unsetNAN(double val=0)
Definition: Image.h:523
int main(int argc, char *argv[])
Definition: deform.cpp:479