Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
decsCLTrimmedICP.cpp
1 
2 #include <mip_config.h>
3 #ifndef DECS_HAVE_WXWIDGETS
4 # error Your DECS needs WX. Please recompile DECS with USE_WXWIDGETS.
5 #endif
6 
7 #include <string>
8 #include <limits>
9 #include <iostream>
10 
11 #include <Base/Common/BIASpragmaStart.hh>
12 #include <Base/Common/BIASpragmaEnd.hh>
13 #include <Base/Image/ImageConvert.hh>
14 #include <Base/Common/FileHandling.hh>
15 #include <Base/CommonUtils/Param.hh>
16 
17 #include <GLviewer/ContextWX.hh>
18 #include <GLviewer/GLProjectionParametersPerspective.hh>
19 #include <GLviewer/Controller/TrackballControl.hh>
20 #include <GLviewer/Scenes/SceneOpenSceneGraph.hh>
21 #include <GLviewer/Scenes/SceneOcTree3D.hh>
22 
23 #include <wx/wx.h>
24 #include <wx/listctrl.h>
25 #include <wx/filename.h>
26 
27 #include <Gui/StringConv.hh>
28 #include <Gui/ConsoleRedirectIO.hh>
29 #include <Gui/ImageCanvas.hh>
30 #include <Gui/biasgl.h>
31 #include <Utils/IOUtils.hh>
32 
33 #include <OpenGLFramework/RenderingContext/glfPBuffer.hh>
34 #include <OpenCLFramework/Algorithm/clfTrimmedICP.hh>
35 #include <OpenGLFramework/RenderingContext/glfRenderingContext.hh>
36 
37 
38 using namespace std;
39 using namespace DECS;
40 using namespace BIAS;
41 
42 enum
43 {
44  ID_Exit,
45  ID_Timer
46 };
47 
48 class MainFrame : public wxFrame
49 {
50 public:
51  MainFrame(std::string depthModel, std::string texModel, std::string depthIn, std::string texIn, int ylast, double zthres, bool closeafterfinish, bool notrefinewithall);
52  int FindLargestOverlappingRegion_(const ProjectionParametersBase *camAproj, const ProjectionParametersBase *camBproj, ROI &roi);
53  bool inited;
54 protected:
55  void OnExit(wxCommandEvent& event);
56  void OnTimer(wxTimerEvent& event);
57  void OnKey(wxKeyEvent& event);
58 
59  ImageCanvas *ic_;
60 
61  clfTrimmedICP *tricp_;
62  wxTimer _timer;
63  int computationStep_;
64 
65  Camera<float> depth1, depth2;
66  Camera<unsigned char> amp1c, amp2c;
67  Camera<float> d1copy, d2copy, d2orig;
68 
69  std::string depthModelName_, texModelName_, depthInName_, texInName_;
70 
71  unsigned int overlapPixels_;
72 
73  bool closeAfterFinish_, notrefinewithall_;
74 
75  BIAS::glfRenderingContext* glcontext_;
76  BIAS::glfTexture2D outputTextureDepth_;
77  BIAS::glfTexture2D outputTextureColor_;
78 
80  BIAS::glfBatch batch_;
81  glfDepthBufferMode depthBufferMode_;
82  glfViewport viewport_;
83  glfMatrix modelviewmatrix;
84  glfMatrix projectionmatrix;
85 
86  unsigned int mpc, dpc;
87 
88  DECLARE_EVENT_TABLE()
89 };
90 
91 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
92  EVT_BUTTON(ID_Exit, MainFrame::OnExit)
93  EVT_TIMER(ID_Timer, MainFrame::OnTimer)
94  EVT_KEY_DOWN(MainFrame::OnKey)
95 END_EVENT_TABLE()
96 
97 void MainFrame::OnKey(wxKeyEvent& event) {
98  //int code = event.GetKeyCode();
99 }
100 
101 
102 void MainFrame::OnExit(wxCommandEvent& /*event*/) {
103  glcontext_->Destroy();
104  Close();
105 }
106 
107 void MainFrame::OnTimer(wxTimerEvent& /*event*/) {
108  _timer.Stop();
109 // cout << "on timer" << endl;
110  if (computationStep_ == 0) {
111 
112  int res = tricp_->Compute(100, 18000);
113  cout << "Compute!" << endl;
114  if (res == 0)
115  computationStep_ = 1;
116  } else if (computationStep_ == 1) {
117  if (notrefinewithall_) {
118  Projection proj(*(tricp_->GetParams()));
119  std::string outname = BIAS::FileHandling::Basename(depthInName_);
120  outname+="-icpaligned.mip";
121  cout << outname << endl;
122  IOUtils::SaveCamera(outname, d2orig, proj);
123  computationStep_ = 3;
124  } else {
125  computationStep_ ++;
126  Projection proj(*(tricp_->GetParams()));
127  d2copy.SetProj(proj);
128 
129  delete tricp_;
130 
131  tricp_ = new clfTrimmedICP;
132  tricp_->SetMaxIterations(100);
133 
134  Projection p1(d1copy.GetProj());
135 
136  // find overlap
137  ROI overlap;
138  FindLargestOverlappingRegion_(proj.GetParameters(), p1.GetParameters(), overlap);
139  cout << overlap << endl;
140  unsigned int corners[4];
141  overlap.GetCorners(corners[0], corners[1], corners[2], corners[3]);
142  overlapPixels_ = (corners[2] - corners[0]) * (corners[3] - corners[1]) * 2 / 3;
143  std::cout << overlapPixels_ << std::endl;
144  mpc = tricp_->SetModelFromDepthMap(d1copy, amp1c);
145  dpc = tricp_->SetDataFromDepthMap(d2copy, amp2c);
146  // todo draw model
147  // todo draw data
148  computationStep_ = 2;
149  }
150  } else if (computationStep_ == 2) {
151  int res = 0;
152 
153  if (overlapPixels_ > 500) {
154  res = tricp_->Compute(20, overlapPixels_);
155  } else {
156  res = tricp_->Compute(20, 8000);
157  }
158  cout << "Compute!" << endl;
159  if (res == 0) {
160  Projection proj(*(tricp_->GetParams()));
161  cout << proj << endl;
162  std::string outname = BIAS::FileHandling::Basename(depthInName_);
163  outname = "aligned-"+outname+".mip";
164  IOUtils::SaveCamera(outname, d2orig, proj);
165  computationStep_ = 3;
166  }
167 
168 
169  } else if (computationStep_ == 3) {
170  tricp_->Fuse(30);
171  if (closeAfterFinish_) {
172  Close();
173  }
174  computationStep_++;
175  }
176 
177  fbo_.ClearColorBuffer(.0f,.0f,.0f,.0f);
178  fbo_.ClearDepthBuffer(1.0f);
179  batch_.SetVertexBuffer( tricp_->GetModel() );
180  batch_.SetRange(0, mpc);
181  batch_.Draw();
182  batch_.SetVertexBuffer( tricp_->GetData() );
183  batch_.SetRange(0, dpc);
184  batch_.Draw();
186 
187  outputTextureColor_.CopyToImage( img );
188  ImageIO::Save("test.mip", img);
189 
190  ic_->Show( img, "img" );
191 
192  glFinish();
193  _timer.Start(5, true);
194 }
195 
196 MainFrame::MainFrame(std::string depthModel, std::string texModel, std::string depthIn, std::string texIn, int ylast, double zthres, bool closeafterfinish, bool notrefinewithall)
197  : wxFrame((wxFrame *)NULL, -1,
198  wxT("Trimmed ICP"),
199  wxPoint(0, 0),
200  wxSize(800, 600))
201 {
202  mpc=0;
203  dpc=0;
204 
205  depthModelName_ = depthModel;
206  texModelName_ = texModel;
207  depthInName_ = depthIn;
208  texInName_ = texIn;
209  closeAfterFinish_ = closeafterfinish;
210  notrefinewithall_ = notrefinewithall;
211  Show(true);
212  inited = true;
213 
214  ic_ = new ImageCanvas(this);
215  ic_->SetSize(800,600);
216 
217  BIAS::Vector3<double> pos(0,0,0);
218  BIAS::Vector4<unsigned char> color(255,0,0,255);
219 
220  Camera<float> amp1, amp2;
221 // Camera<unsigned char> amp1, amp2;
222  Projection p1;
223  IOUtils::LoadCamera(&depthModelName_, depth1, p1);
224  depth1.ParseMetaData();
225  IOUtils::LoadCamera(&depthInName_, depth2);
226  depth2.ParseMetaData();
227  IOUtils::LoadCamera(&texModelName_, amp1);
228  IOUtils::LoadCamera(&texInName_, amp2);
229  amp1.ScaleShiftBetween(0,255);
230  amp2.ScaleShiftBetween(0,255);
231  amp1c.Init(amp1.GetWidth(), amp1.GetHeight(), 3);
232  amp2c.Init(amp2.GetWidth(), amp2.GetHeight(), 3);
233  unsigned char **a1c = amp1c.GetImageDataArray();
234  unsigned char **a2c = amp2c.GetImageDataArray();
235  float **a1 = amp1.GetImageDataArray();
236  float **a2 = amp2.GetImageDataArray();
237 // unsigned char **a1 = amp1.GetImageDataArray();
238 // unsigned char **a2 = amp2.GetImageDataArray();
239 
240  d1copy = depth1;
241  d2copy = depth2;
242  d2orig = depth2;
243 
244  float **d1 = depth1.GetImageDataArray();
245  float **d2 = depth2.GetImageDataArray();
246  for (unsigned int y=0;y<amp1.GetHeight();y++) {
247  for (unsigned int x=0;x<amp1.GetWidth();x++) {
248 // if (/*d1[y][x] > 1500 || */ y > 123) {
249 // d1[y][x] = 0;
250 // }
251 // if (/*d2[y][x] > 1500 || */ y > 123) {
252 // d2[y][x] = 0;
253 // }
254  if (d1[y][x] > zthres || y > (unsigned int)ylast) {
255  d1[y][x] = 0;
256  }
257  if (d2[y][x] > zthres || y > (unsigned int)ylast) {
258  d2[y][x] = 0;
259  }
260  a1c[y][x*3+0] = (unsigned char)a1[y][x];
261  a1c[y][x*3+1] = 0;
262  a1c[y][x*3+2] = 0;
263  a2c[y][x*3+0] = 0;
264  a2c[y][x*3+1] = (unsigned char)a2[y][x];;
265  a2c[y][x*3+2] = 0;
266  }
267  }
268 
269  glcontext_ = new glfPBuffer;
270 
271  unsigned int w=0,h=0;
272  p1.GetParameters()->GetImageSize(w,h);
273 
274  // fill configuration
276  cfg.width = w;
277  cfg.height = h;
278  cfg.doubleBuffer = 0;
279  cfg.redSize = 8;
280  cfg.greenSize = 8;
281  cfg.blueSize = 8;
282  cfg.alphaSize = 8;
283  cfg.depthSize = 24;
284  cfg.stencilSize = 0;
285 
286  // initialize context
287  glcontext_->Init(cfg);
288 
289  computationStep_ = 0;
290 
291  tricp_ = new clfTrimmedICP(amp1.GetWidth(), amp1.GetHeight());
292 
293  tricp_->SetMaxIterations(1000);
294 
295  mpc = tricp_->SetModelFromDepthMap(depth1, amp1c);
296  dpc = tricp_->SetDataFromDepthMap(depth2, amp2c);
297 
298  _timer.SetOwner(this, ID_Timer);
299  _timer.Start(5,true);
300  cout << "camera on" << endl;
301  //Refresh();
302  cout << "refresh" << endl;
303 
304  outputTextureDepth_.Create();
305  outputTextureDepth_.Set();
306  outputTextureDepth_.Allocate(w,h, GL_DEPTH_COMPONENT24);
307 
308  outputTextureColor_.Create();
309  outputTextureColor_.Set();
310  outputTextureColor_.Allocate(w,h, GL_RGBA);
311 
312  fbo_.Create();
313 
314  fbo_.AttachTexture(outputTextureColor_, GL_COLOR_ATTACHMENT0_EXT);
315  fbo_.AttachTexture(outputTextureDepth_, GL_DEPTH_ATTACHMENT_EXT);
316  fbo_.CheckComplete();
317 
318  // create depth buffer mode
319  depthBufferMode_.SetDepthTest(true);
320  viewport_.SetOrigin(0, 0);
321  viewport_.SetSize(w,h);
322 
324  float zNear = 10.0f;
325  float zFar = 10000.0f;
326  projectionmatrix.MakeProjectionMatrixNew(*pp, zNear, zFar, true);
327  modelviewmatrix.MakeViewMatrixNew(*pp);
328 
329  // create and draw batch
330  batch_.SetDepthBufferMode(&depthBufferMode_);
331  batch_.SetPrimitiveType(GL_POINTS);
332  batch_.SetViewport(&viewport_);
333  batch_.SetRenderTarget(&fbo_);
334  batch_.SetModelViewMatrix(&modelviewmatrix);
335  batch_.SetProjectionMatrix(&projectionmatrix);
336  glPointSize(3);
337 
338 }
339 
340 int MainFrame::FindLargestOverlappingRegion_(const ProjectionParametersBase *camAproj,
341  const ProjectionParametersBase *camBproj, ROI &roi) {
342 
343  vector<ProjectionParametersBase *> source;
344  vector<float **> depths;
345  depths.resize(2);
346  source.resize(2);
347  source[0] = (ProjectionParametersBase*) camAproj;
348  source[1] = (ProjectionParametersBase*) camBproj;
349  depths[0] = d1copy.GetImageDataArray();
350  depths[1] = d2copy.GetImageDataArray();
351  cout << source[0] << endl << source[1] << endl;
352  PixelIterator it;
353  unsigned int w, h;
354  camAproj->GetImageSize(w, h);
355  unsigned int xmin = 0, xmax = w, ymin = 0, ymax = h;
356  for (unsigned int i = 0; i < source.size(); i++) {
357  // mid point
358  unsigned int mx, my;
359  source[i]->GetImageSize(mx, my);
360  HomgPoint2D midPoint(mx / 2, my / 2, 1);
361  HomgPoint3D point3D = source[i]->UnProjectToPoint(midPoint, depths[i][my/2][mx/2]);
362  point3D.Homogenize();
363  midPoint = source[(i+1)%2]->Project(point3D);
364  source[i]->GetFirstBorderPixel(it);
365  HomgPoint2D edgepoint(0, 0, 0);
366  HomgPoint2D oldPoint = edgepoint;
367  do {
368  HomgPoint2D sourcepoint(it.x, it.y, 1);
369  point3D = source[i]->UnProjectToPoint(sourcepoint, depths[i] [ (unsigned int)it.y][ (unsigned int)it.x]);
370  point3D.Homogenize();
371  edgepoint = source[(i+1)%2]->Project(point3D);
372  edgepoint.Homogenize();
373  if (edgepoint[0] > 0 && edgepoint[0] < w && edgepoint[1]>0 && edgepoint[1] < h) {
374  // get distance vector to midpoint
375  HomgPoint2D dist = sourcepoint - midPoint;
376  HomgPoint2D grad = sourcepoint - oldPoint;
377 
378  // going right (or left)
379  if (abs(grad[0]) > abs(grad[1])) {
380  if (dist[1] < 0) {
381  if (edgepoint[1] > ymin) {
382  ymin = edgepoint[1];
383  }
384  } else {
385  if (edgepoint[1] < ymax) {
386  ymax = edgepoint[1];
387  }
388  }
389  } // going up (or down)
390  else {
391  if (dist[0] < 0) {
392  if (edgepoint[0] > xmin) {
393  xmin = edgepoint[0];
394  }
395  } else {
396  if (edgepoint[0] < xmax) {
397  xmax = edgepoint[0];
398  }
399  }
400  }
401  }
402  oldPoint = sourcepoint;
403  } while (source[i]->GetNextBorderPixel(it));
404  }
405  roi.SetCorners(xmin, ymin, xmax, ymax);
406  return 0;
407 }
408 
409 
410 
411 
412 class icpapp : public wxApp
413 {
414 public:
415  virtual bool OnInit();
416 };
417 
418 bool icpapp::OnInit()
419 
420 {
421 
422  Param *p = new Param();
423 
424  std::string *mdn = p->AddParamString("depthModel", "name of depthmap model", "bp-dud-CAM02Depth-00700.mip", 'm');
425  std::string *mtn = p->AddParamString("texModel", "name of texture model", "bp-CAM02Amp-00700.mip", 't');
426  std::string *idn = p->AddParamString("depthInput", "name of depthmap to be aligned", "bp-dud-CAM02Depth-00800.mip", 'i');
427  std::string *itn = p->AddParamString("texInput", "name of texture to be aligned", "bp-CAM02Amp-00800.mip", 'n');
428  int *ylast = p->AddParamInt("ythres", "cut image in y dir here", -1, 0, INT_MAX, 'y');
429  double *zthres = p->AddParamDouble("zthres", "depth threshold" , -1, 0, 10000, 'z');
430  bool *closeme = p->AddParamBool("closeAfterFinish", "close wx window after finish", false, 'x');
431  bool *notrefinewithall = p->AddParamBool("notrefineonall", "z threshold will not be unset after first optimum found", false);
432 
433  p->ParseCommandLine(argc,WxToAsciiArray(argv, argc));
434 
435  p->ShowData();
436 
437  // create main frame
438  MainFrame* mainFrame = new MainFrame(*mdn, *mtn, *idn, *itn, *ylast, *zthres, *closeme, *notrefinewithall);
439  mainFrame->Show(true);
440  SetTopWindow(mainFrame);
441 
442 
443  //ConsoleRedirectIO();
444 
445  return true;
446 }
447 
448 IMPLEMENT_APP(icpapp)
449 
Defines the usage of the depth buffer.
class for handling different region of interest (ROI) representations...
Definition: ROI.hh:118
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
Definition: ROI.cpp:287
A 2D texture.
Definition: glfTexture2D.hh:40
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
int ScaleShiftBetween(double Min, double Max)
scales and shifts image so afterwards every pixel has a value between Min and Max ...
Definition: Image.cpp:1118
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
double * AddParamDouble(const std::string &name, const std::string &help, double deflt=0.0, double min=-DBL_MAX, double max=DBL_MAX, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:351
display image in wx application, provides zoom and investigation functionality
Definition: ImageCanvas.hh:38
void Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint3D.hh:308
A batch represents a single Draw call including all parameters (render states).
Definition: glfBatch.hh:48
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int ParseCommandLine(int &argc, char *argv[])
scan command line arguments for valid parameters
Definition: Param.cpp:1028
Interface for OpenGL rendering contexts.
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
static std::string Basename(const std::string &fullname)
Get file base name without path from given path and filename.
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
class for setting viewports
Definition: glfViewport.hh:37
unsigned int GetHeight() const
Definition: ImageBase.hh:319
GLX pbuffer rendering context.
void SetMaxIterations(unsigned int maxiterations)
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
Can be used to run along the image border.
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
double x
If using BorderPixel methods these are the coordinates of the pixel.
This class Param provides generic support for parameters.
Definition: Param.hh:231
A 4x4 matrix in native OpenGL format.
Definition: glfMatrix.hh:41
Class for converting an array of wxStrings to an array of non-const ASCII strings.
Definition: StringConv.hh:60
int * AddParamInt(const std::string &name, const std::string &help, int deflt=0, int min=std::numeric_limits< int >::min(), int max=std::numeric_limits< int >::max(), char cmdshort=0, int Group=GRP_NOSHOW)
For all adding routines:
Definition: Param.cpp:276
void ShowData(std::ostream &os=std::cout, int grp=GRP_ALL, bool showenhanced=true)
print all data in group grp including current values to os if grp = GRP_ALL, print all values if show...
Definition: Param.cpp:121
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
std::string * AddParamString(const std::string &name, const std::string &help, std::string deflt="", char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:327
Configuration for a rendering context.
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153