Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasshowepiwx.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #ifdef WIN32
26 // disable warning noise
27 # pragma warning(disable: 4251) // STL MAP DLL
28 # pragma warning(disable: 4005) // VS8 wx
29 # pragma warning(disable: 4996) // wx localtime
30 
31 # include <conio.h> // _getch
32 #endif //WIN32
33 
34 #include <Gui/ConsoleRedirectIO.hh>
35 #include <Gui/ImageCanvas.hh>
36 #include <Gui/PlainImageCanvas.hh>
37 #include <Gui/StringConv.hh>
38 #include <Base/Common/W32Compat.hh>
39 #include <Base/Image/ImageIO.hh>
40 #include <Base/ImageUtils/ImageDraw.hh>
41 #include <Base/Image/ImageConvert.hh>
42 #include <Base/ImageUtils/Bresenham.hh>
43 #include <Image/Camera.hh>
44 #include <Geometry/PMatrix.hh>
45 #include <Geometry/FMatrix.hh>
46 #include <Geometry/EpipolarLine.hh>
47 #include <Geometry/ProjectionParametersSpherical.hh>
48 
49 #include <wx/wx.h>
50 #include <wx/splitter.h>
51 
52 #include <iostream>
53 
54 using namespace std;
55 using namespace BIAS;
56 
57 
58 /**
59  @file
60  @ingroup g_tools
61  @brief show epipolar lines for image pair (WX Version), see biasshowepiwx.cpp
62  @author koeser
63 */
64 
65 /*
66 ===============================================================================
67 Constants
68 ===============================================================================
69 */
70 
71 const int HALF_CUTOUT_SIZE = 30;
72 const int CUTOUT_SIZE = 2 * HALF_CUTOUT_SIZE;
73 const int SCALE = 4;
74 
75 /*
76 ===============================================================================
77 ComputeCutoutImage
78 ===============================================================================
79 */
80 
81 void ComputeCutoutImage(Image<unsigned char>& src, Image<unsigned char>& dst,
82  int srcX, int srcY, int srcWidth, int srcHeight, int scale)
83 {
84  int dstWidth = srcWidth * scale;
85  int dstHeight = srcHeight * scale;
86 
87  if ((int)dst.GetWidth() != dstWidth || (int)dst.GetHeight() != dstHeight)
88  dst.Release();
89 
90  if (dst.IsEmpty())
91  dst.Init(dstWidth, dstHeight, 3);
92 
93  unsigned char** srcIda = src.GetImageDataArray();
94  unsigned char** dstIda = dst.GetImageDataArray();
95 
96  for (int x = srcX; x < srcX + srcWidth; x++)
97  {
98  for (int y = srcY; y < srcY + srcHeight; y++)
99  {
100  unsigned char pixel[3];
101  if (x < 0 || y < 0 || x >= (int)src.GetWidth() || y >= (int)src.GetHeight())
102  {
103  pixel[0] = 0;
104  pixel[1] = 0;
105  pixel[2] = 0;
106  }
107  else
108  {
109  if (src.GetColorModel() == ImageBase::CM_Grey)
110  {
111  pixel[0] = srcIda[y][x];
112  pixel[1] = srcIda[y][x];
113  pixel[2] = srcIda[y][x];
114  }
115  else
116  {
117  // assuming CM_RGB
118  pixel[0] = srcIda[y][3*x+0];
119  pixel[1] = srcIda[y][3*x+1];
120  pixel[2] = srcIda[y][3*x+2];
121  }
122  }
123 
124  int startX = (x - srcX) * scale;
125  int startY = (y - srcY) * scale;
126 
127  for (int i = startX; i < startX + scale; i++)
128  {
129  for (int j = startY; j < startY + scale; j++)
130  {
131  if (i >= 0 && j >= 0 && i < (int)dst.GetWidth() && j < (int)dst.GetHeight())
132  {
133  dstIda[j][3*i+0] = pixel[0];
134  dstIda[j][3*i+1] = pixel[1];
135  dstIda[j][3*i+2] = pixel[2];
136  }
137  }
138  }
139  }
140  }
141 }
142 
143 /** \cond HIDDEN_SYMBOLS
144  * \class CutoutFrame - Frame showing a cutout of a larger image
145 */
146 class CutoutFrame : public wxFrame
147 {
148 public:
149  CutoutFrame(wxWindow* parent, const wxString& title);
150 
151  void ShowImage(Image<unsigned char>& image, const string& name);
152  void SetTransform(int offsetX, int offsetY, int scale);
153 
154 private:
155  int _OffsetX, _OffsetY, _Scale;
156  PlainImageCanvas* _ImageCanvas;
157 
158  void OnMotion(wxMouseEvent& event);
159  void OnLeaveWindow(wxMouseEvent& event);
160  void OnClose(wxCloseEvent& event);
161  void OnKeyDown(wxKeyEvent& keyEvent);
162  void OnCharEvt(wxKeyEvent& keyEvent);
163 
164 
165  DECLARE_EVENT_TABLE()
166 };
167 /** \endcond */
168 
169 BEGIN_EVENT_TABLE(CutoutFrame, wxFrame)
170 EVT_MOTION(CutoutFrame::OnMotion)
171 EVT_LEAVE_WINDOW(CutoutFrame::OnLeaveWindow)
172 EVT_CLOSE(CutoutFrame::OnClose)
173 EVT_KEY_DOWN(CutoutFrame::OnKeyDown)
174 EVT_CHAR(CutoutFrame::OnCharEvt)
175 END_EVENT_TABLE()
176 
177 void CutoutFrame::OnKeyDown(wxKeyEvent& event)
178 {
179  if (GetParent() != NULL)
180  {
181  GetParent()->GetEventHandler()->ProcessEvent(event);
182  }
183 }
184 
185 
186 void CutoutFrame::OnCharEvt(wxKeyEvent& event)
187 {
188  if (GetParent() != NULL)
189  {
190  GetParent()->GetEventHandler()->ProcessEvent(event);
191  }
192 }
193 
194 
195 CutoutFrame::CutoutFrame(wxWindow* parent, const wxString& title)
196  : wxFrame(parent, -1, title,
197  wxDefaultPosition, wxDefaultSize,
198  wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT)
199 {
200  _OffsetX = 0;
201  _OffsetY = 0;
202  _Scale = 1;
203 
204  _ImageCanvas = new PlainImageCanvas(this);
205 
206  CreateStatusBar(1);
207 
208  wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
209  sizer->Add(_ImageCanvas);
210  SetSizer(sizer);
211 }
212 
213 void CutoutFrame::ShowImage(Image<unsigned char>& image, const string& name)
214 {
215  _ImageCanvas->Show(image, name);
216  _ImageCanvas->SetScrollbars(0, 0, 0, 0);
217  GetSizer()->SetItemMinSize(_ImageCanvas, image.GetWidth(), image.GetHeight());
218  Fit();
219 }
220 
221 void CutoutFrame::SetTransform(int offsetX, int offsetY, int scale)
222 {
223  _OffsetX = offsetX;
224  _OffsetY = offsetY;
225  _Scale = scale;
226 }
227 
228 void CutoutFrame::OnMotion(wxMouseEvent& event)
229 {
230  wxClientDC dc(this);
231  PrepareDC(dc);
232  wxPoint pos = event.GetPosition();
233  int x = dc.DeviceToLogicalX(pos.x) / _Scale + _OffsetX;
234  int y = dc.DeviceToLogicalY(pos.y) / _Scale + _OffsetY;
235  stringstream text;
236  text << "(x, y) = (" << x << ", " << y << ")";
237  GetStatusBar()->SetStatusText(AsciiToWx(text.str()));
238 }
239 
240 void CutoutFrame::OnLeaveWindow(wxMouseEvent&)
241 {
242  GetStatusBar()->SetStatusText(wxT(""));
243 }
244 
245 void CutoutFrame::OnClose(wxCloseEvent& event)
246 {
247  if (event.CanVeto())
248  {
249  Hide();
250  event.Veto();
251  }
252  else
253  {
254  Destroy();
255  }
256 }
257 
258 /*
259 ===============================================================================
260 MainFrame
261 ===============================================================================
262 */
263 
264  enum{
265  ID_THICKER_LINE= wxID_HIGHEST+100,
266  ID_THINNER_LINE,
267  ID_SAVE_IMAGES
268  };
269  /** \cond HIDDEN_SYMBOLS */
270 class MainFrame : public wxFrame
271 {
272 public:
273  MainFrame();
274 
275  void SetImages(Image<unsigned char>& image1, const Projection& proj1,
276  const string& name1,
277  Image<unsigned char>& image2, const Projection& proj2,
278  const string& name2, bool homographymode = false);
279  double GenerateVirtualPerspectiveCamera(ProjectionParametersBase *paramsSpherical1,
280  ProjectionParametersPerspective *fakeParamsPersp1,
281  const double& maximagewidth);
282 private:
283  /// if in homography only mode:
284  bool onlyHomography_;
285  /// this cotains the last clicked point in image1 backprojected onto
286  /// plane at infinity
287  HomgPoint3D pointatinfinity_;
288  PlainImageCanvas* _ImageCanvas1;
289  PlainImageCanvas* _ImageCanvas2;
290  Image<unsigned char> _Image1, _Image2;
291  Image<unsigned char> PaintedImage1_, PaintedImage2_;
292  Projection _Projection1, _Projection2;
293  std::string _ImageName1, _ImageName2;
294  CutoutFrame* _CutoutFrame1;
295  CutoutFrame* _CutoutFrame2;
296  wxPoint _SelectedPoint1; // selected point in left image
297  wxPoint _SelectedPoint2; // selected point in right image
298 
299  void OnLeftDown(wxMouseEvent& event);
300  void OnKeyDown(wxKeyEvent& keyEvent);
301  void OnCharEvt(wxKeyEvent& keyEvent);
302  void ThickerLine(wxCommandEvent& event);
303  void ThinnerLine(wxCommandEvent& event);
304  void SaveImages(wxCommandEvent& event);
305 
306  wxMenuBar* menuBar_;
307  wxMenu* file_;
308 // wxMenuItem* save_;
309 
310  wxMenu* drawing_;
311 // wxMenuItem* thicker_;
312 // wxMenuItem* thinner_;
313 
314 
315  int epiLineWidth_;
316  DECLARE_EVENT_TABLE()
317 };
318 /** \endcond */
319 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
320 EVT_LEFT_DOWN(MainFrame::OnLeftDown)
321 EVT_MENU(ID_THICKER_LINE, MainFrame::ThickerLine)
322 EVT_MENU(ID_THINNER_LINE, MainFrame::ThinnerLine)
323 EVT_MENU(ID_SAVE_IMAGES, MainFrame::SaveImages)
324 END_EVENT_TABLE()
325 
326 void MainFrame::SaveImages(wxCommandEvent& event){
327  ImageIO::Save("paintedImage1.mip",PaintedImage1_);
328  ImageIO::Save("paintedImage2.mip",PaintedImage2_);
329 }
330 
331 void MainFrame::ThickerLine(wxCommandEvent& event)
332 {
333  epiLineWidth_ ++;
334  cout<<" "<<epiLineWidth_<<endl;
335  int x1, y1, x2, y2;
336  _ImageCanvas1->GetViewStart(&x1, &y1);
337  _ImageCanvas1->GetViewStart(&x2, &y2);
338  _ImageCanvas1->Show(_Image1, _ImageName1);
339  _ImageCanvas2->Show(_Image2, _ImageName2);
340  _ImageCanvas1->Scroll(x1, y1);
341  _ImageCanvas1->Scroll(x2, y2);
342 
343 }
344 
345 void MainFrame::ThinnerLine(wxCommandEvent& event)
346 {
347  epiLineWidth_ --;
348  if(epiLineWidth_<1) epiLineWidth_=1;
349  cout<<" "<<epiLineWidth_<<endl;
350  int x1, y1, x2, y2;
351  _ImageCanvas1->GetViewStart(&x1, &y1);
352  _ImageCanvas1->GetViewStart(&x2, &y2);
353  _ImageCanvas1->Show(_Image1, _ImageName1);
354  _ImageCanvas2->Show(_Image2, _ImageName2);
355  _ImageCanvas1->Scroll(x1, y1);
356  _ImageCanvas1->Scroll(x2, y2);
357 
358 }
359 
360 
361 
362 
363 MainFrame::MainFrame()
364  : wxFrame(NULL, -1, wxT("BiasShowEpiWX")),
365  pointatinfinity_ (0.0, 0.0, 0.0, 0.0), epiLineWidth_(1)
366 {
367  _CutoutFrame1 = new CutoutFrame(this, wxT("Cutout 1"));
368  _CutoutFrame2 = new CutoutFrame(this, wxT("Cutout 2"));
369  onlyHomography_ = false;
370  CreateStatusBar();
371 
372  _ImageCanvas1 = new PlainImageCanvas(this, GetStatusBar(), 0);
373  _ImageCanvas2 = new PlainImageCanvas(this, GetStatusBar(), 0);
374 
375  menuBar_ = new wxMenuBar;
376  file_ = new wxMenu;
377  file_->Append(ID_SAVE_IMAGES, wxT("&Save"));
378 
379  drawing_ = new wxMenu;
380  drawing_->Append(ID_THICKER_LINE, wxT("&Increase Line Width"));
381  drawing_->Append(ID_THINNER_LINE, wxT("&Decrease Line Width"));
382 
383 
384  menuBar_->Append(file_, wxT("&File"));
385  menuBar_->Append(drawing_, wxT("&Display"));
386  SetMenuBar(menuBar_);
387 
388 
389 // wxAcceleratorEntry entries[2];
390 // entries[0].Set(wxACCEL_NORMAL, WXK_SPACE, ID_FAKE_UP);
391 // //entries[1].Set(wxACCEL_NORMAL, WXK_DOWN, ID_FAKE_DOWN);
392 // wxAcceleratorTable accel(2, entries);
393 // SetAcceleratorTable(accel);
394 }
395 
396 
397 
398 void DrawEpipole(Image<unsigned char>& image1,
399  const Projection& proj1, const Projection& proj2) {
400  HomgPoint2D orig_epipole;
401  const unsigned char Value[3]={255,0,0};
402  bool epipoleIsInImage =
404  orig_epipole);
405 
406  if (epipoleIsInImage) {
408  int(rint(orig_epipole[0])),
409  int(rint(orig_epipole[1])),
410  5, Value);
412  int(rint(orig_epipole[0])),
413  int(rint(orig_epipole[1])),
414  6, Value);
415  }
416 
417 }
418 
419 void ShowSphericalParameters(Image<unsigned char>& image1,
420  const Projection& proj1) {
421  const ProjectionParametersSpherical *pPPS =
422  dynamic_cast<const ProjectionParametersSpherical* >(proj1.GetParameters());
423 
424  if (pPPS!=NULL) {
425  const unsigned char Blue[3]={0,0,255};
426  const unsigned char Green[3]={0,255,0};
427  int radius = (int(rint(pPPS->GetRadius())));
428  HomgPoint2D pp(0,0,1);
429  pPPS->GetPrincipal(pp[0], pp[1]);
430  ImageDraw<unsigned char>::CircleCenter(image1, int(rint(pp[0])),
431  int(rint(pp[1])),
432  int(rint(radius)),
433  Green);
434  ImageDraw<unsigned char>::CircleCenter(image1, int(rint(pp[0])),
435  int(rint(pp[1])),
436  int(rint(radius+1)),
437  Green);
438  for (unsigned int i = 0; i<4; i++) {
439  Vector3<double> ray(tan(30.0*double(i)*M_PI / 180.0),0,1);
440  HomgPoint2D point = pPPS->ProjectLocal(ray);
441  if (point.NormL2()<1e-10) break;
442  ImageDraw<unsigned char>::CircleCenter(image1, int(rint(pp[0])),
443  int(rint(pp[1])),
444  int(rint((point-pp).NormL2())),
445  Blue);
446  }
447  }
448 }
449 
450 void MainFrame::SetImages(Image<unsigned char>& image1,
451  const Projection& proj1, const string& name1,
452  Image<unsigned char>& image2,
453  const Projection& proj2, const string& name2,
454  bool homographymode)
455 {
456  PaintedImage1_ = _Image1 = image1;
457  PaintedImage2_ = _Image2 = image2;
458  _Projection1 = proj1;
459  _Projection2 = proj2;
460 
462  dynamic_cast<ProjectionParametersPerspective *>(_Projection1.GetParameters());
464  dynamic_cast<ProjectionParametersPerspective *>(_Projection2.GetParameters());
465  if (ppp1!=NULL && ppp2!=NULL) {
466  PMatrix P1 = ppp1->GetP();
467  PMatrix P2 = ppp2->GetP();
468  FMatrix F(P1, P2);
469  cout<<"F is "<<F<<endl;
470  }
471 
472 
473 
474 
475 
476 
477 
478  _ImageName1 = name1;
479  _ImageName2 = name2;
480 
481  if (((_Projection1.GetC()-_Projection2.GetC()).NormL2()<1e-8)
482  || homographymode) {
483  BIASWARN(endl<<endl<<endl<<
484  "Homography mode or very small baseline, using only H_infinity!"
485  <<endl<<endl<<endl);
486  onlyHomography_ = true;
487  }
488 
489  DrawEpipole(_Image1, _Projection1, _Projection2);
490  DrawEpipole(_Image2, _Projection2, _Projection1);
491 
492  ShowSphericalParameters(_Image1, _Projection1);
493  ShowSphericalParameters(_Image2, _Projection2);
494 
495  _ImageCanvas1->Show(_Image1, _ImageName1);
496  _ImageCanvas2->Show(_Image2, _ImageName2);
497  _ImageCanvas1->SetClearDrawingContext(false);
498  _ImageCanvas2->SetClearDrawingContext(false);
499 
500  wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
501  sizer->Add(_ImageCanvas1, 1, wxEXPAND);
502  sizer->AddSpacer(3);
503  sizer->Add(_ImageCanvas2, 1, wxEXPAND);
504 
505  sizer->SetItemMinSize(_ImageCanvas1, 100, 100);
506  sizer->SetItemMinSize(_ImageCanvas2, 100, 100);
507 
508  SetSizer(sizer);
509  sizer->SetSizeHints(this);
510 
511  SetSize(900, 600); // default main frame size
512 }
513 
514 double MainFrame::
515 GenerateVirtualPerspectiveCamera(ProjectionParametersBase
516  *paramsSpherical1,
518  *fakeParamsPersp1,
519  const double& maximagewidth) {
520 
521  double imageSize = maximagewidth + 1.0;
522  // start near 180 degree fov
523  double maxangle = M_PI/2.0-0.01;
524  KMatrix K(MatrixZero);
525  // decrease fov angle until perspective image is smaller than maximagewidth
526  while (imageSize>maximagewidth) {
527  K = paramsSpherical1->GetFakeKMatrix(imageSize, 1, maxangle);
528  maxangle -= 0.01;
529  BIASASSERT(maxangle>0.0);
530  }
531  fakeParamsPersp1->SetC(paramsSpherical1->GetC());
532  fakeParamsPersp1->SetQ(paramsSpherical1->GetQ());
533  fakeParamsPersp1->SetK(K);
534  fakeParamsPersp1->SetImageSize((int)imageSize, (int)imageSize);
535 
536  return imageSize;
537 }
538 
539 void MainFrame::OnLeftDown(wxMouseEvent& event)
540 {
541  // epipolar lines are nicest handled in perspective images:
542  ProjectionParametersPerspective* paramsPersp1 =
543  dynamic_cast<ProjectionParametersPerspective*>
544  (_Projection1.GetParameters());
545  int image1Width = _Image1.GetWidth();
546  int image1Height = _Image1.GetHeight();
547 
548  // check whether we must emulate perspective projection:
549  ProjectionParametersPerspective fakeParamsPersp1;
550  if (paramsPersp1==NULL) {
551  // make sure the emulated image coordinates dont go above 100000 otherwise
552  // we might get memory problems
553  image1Width = image1Height = (int)rint(
554  GenerateVirtualPerspectiveCamera(_Projection1.GetParameters(),
555  &fakeParamsPersp1,
556  image1Width*100.0));
557  paramsPersp1 = &fakeParamsPersp1;
558  cout<<"Simulating epipolar geometry with perspective image of size "
559  <<image1Width<<endl;
560  }
561 
562  // do the same for the other image
563  ProjectionParametersPerspective* paramsPersp2 =
564  dynamic_cast<ProjectionParametersPerspective*>(_Projection2.GetParameters());
565 
566  int image2Width = _Image2.GetWidth();
567  int image2Height = _Image2.GetHeight();
568 
569  // check whether we must emulate perspective projection for cam2:
570  ProjectionParametersPerspective fakeParamsPersp2;
571  if (paramsPersp2==NULL) {
572 
573  image2Width = image2Height =
574  (int)rint(GenerateVirtualPerspectiveCamera(_Projection2.GetParameters(),
575  &fakeParamsPersp2,
576  image2Width * 100.0));
577  paramsPersp2 = &fakeParamsPersp2;
578  }
579 
580  PMatrix P1 = paramsPersp1->GetP();
581  PMatrix P2 = paramsPersp2->GetP();
582  if (event.GetEventObject() == _ImageCanvas1) {
583  wxClientDC dc(this);
584  _ImageCanvas1->PrepareDC(dc);
585  //wxPoint pos = event.GetPosition();
586  _SelectedPoint1.x = dc.DeviceToLogicalX(event.GetX());
587  _SelectedPoint1.y = dc.DeviceToLogicalY(event.GetY());
588 
589 
590  HomgPoint2D point(_SelectedPoint1.x, _SelectedPoint1.y, 1.0);
591 
592  // undistort the clicked point
593  if (paramsPersp1== NULL) {
594  Vector3<double> ray, pos;
595  _Projection1.GetParameters()->UnProjectLocal(point, pos, ray);
596  if (ray.NormL2()<1e-12) {
597  BIASERR("clicked on point out of valid area !");
598  } else {
599  point = paramsPersp1->ProjectLocal(ray);
600  }
601  }
602  else // no fake KMatrix, just perspective distortion
603  {
604  paramsPersp1->Undistort(point);
605  }
606  point.Homogenize();
607 
608  // images including selected point and epipolar lines
609  PaintedImage1_ = _Image1;
610  PaintedImage2_ = _Image2;
611 
612  // --- LEFT IMAGE ---
613 
614 
615  // draw the selected point in PaintedImage1
617  _SelectedPoint1.x,
618  _SelectedPoint1.y,
619  CUTOUT_SIZE);
620 
621  Vector3<double> p, dir;
622  _Projection1.UnProjectToRay(HomgPoint2D(_SelectedPoint1.x, _SelectedPoint1.y, 1.0), p, dir);
623  pointatinfinity_ =
624  HomgPoint3D(dir);
625  pointatinfinity_[3] = 0.0;
626  cout<<"Point at infinity is "<<pointatinfinity_<<endl;
627  cout<<"line width "<<epiLineWidth_<<endl;
628  HomgPoint2D pointimage2(0,0,0);
629  if (_Projection2.DoesPointProjectIntoImage(pointatinfinity_,
630  pointimage2)) {
631  pointimage2.Homogenize();
632  // draw the transferred point in PaintedImage2
634  int(rint(pointimage2[0])),
635  int(rint(pointimage2[1])),
636  5);
637  } else {
638  BIASERR("Point at infinity does not project into image 2:"<<pointimage2);
639  }
640  if (!onlyHomography_){
641  // compute epipoles in big image
642  FMatrix F12(P1, P2);
643  HomgPoint2D epipole1, epipole2;
644  F12.GetEpipolesHomogenized(epipole1, epipole2);
645 
646  // compute the projection of the epipolar plane for that point
647  EpipolarLine eline1 = epipole1.CrossProduct(point);
648  if (eline1.NormL2()>1e-10) {
649 
650  HomgPoint2D clickedpoint(_SelectedPoint1.x, _SelectedPoint1.y);
651  Vector3<double> pointOnRay, dirRay;
652  _Projection1.UnProjectToRay(clickedpoint, pointOnRay, dirRay);
653 
655  PaintedImage1_,
656  _Projection2.GetC(),
657  dirRay,
658  (unsigned char*)NULL,
659  epiLineWidth_);
660  _Projection1.UnProjectToRay(clickedpoint, pointOnRay, dirRay);
662  PaintedImage2_,
663  _Projection1.GetC(),
664  dirRay,
665  (unsigned char*)NULL,
666  epiLineWidth_);
667 
668 
669  } else {
670  BIASERR("You clicked ("<<_SelectedPoint1.x<<";"<<_SelectedPoint1.y
671  <<" which is undefined or pretty close to the epipole "
672  <<" , in idealized perspective image "<<point<<" and epipole="
673  <<epipole1
674  <<" resulting in eline "<<eline1);
675  }
676  }
677  // show images (and restore scrollbar positions after that)
678  int x1, y1, x2, y2;
679  _ImageCanvas1->GetViewStart(&x1, &y1);
680  _ImageCanvas1->GetViewStart(&x2, &y2);
681  _ImageCanvas1->Show(PaintedImage1_, _ImageName1);
682  _ImageCanvas2->Show(PaintedImage2_, _ImageName2);
683  _ImageCanvas1->Scroll(x1, y1);
684  _ImageCanvas1->Scroll(x2, y2);
685 
686  // --- CUTOUT FOR LEFT IMAGE ---
687  Image<unsigned char> CutoutImage;
688  ComputeCutoutImage(_Image1, CutoutImage,
689  _SelectedPoint1.x - HALF_CUTOUT_SIZE,
690  _SelectedPoint1.y - HALF_CUTOUT_SIZE,
691  CUTOUT_SIZE, CUTOUT_SIZE, SCALE);
693  RectangleCenter(CutoutImage,
694  2 + (_SelectedPoint1.x - (_SelectedPoint1.x - HALF_CUTOUT_SIZE)) * SCALE,
695  2 + (_SelectedPoint1.y - (_SelectedPoint1.y - HALF_CUTOUT_SIZE)) * SCALE, SCALE);
697  2 + (_SelectedPoint1.x - (_SelectedPoint1.x - HALF_CUTOUT_SIZE)) * SCALE,
698  2 + (_SelectedPoint1.y - (_SelectedPoint1.y - HALF_CUTOUT_SIZE)) * SCALE, SCALE * 4);
699 
700  _CutoutFrame1->ShowImage(CutoutImage, _ImageName1);
701  _CutoutFrame1->SetTransform(_SelectedPoint1.x - HALF_CUTOUT_SIZE,
702  _SelectedPoint1.y - HALF_CUTOUT_SIZE, SCALE);
703  _CutoutFrame1->Show(TRUE);
704  _CutoutFrame1->Fit();
705 
706 
707  }
708  // store selected point when clicked in image 2
709  if (event.GetEventObject() == _ImageCanvas2)
710  {
711  wxClientDC dc(this);
712  _ImageCanvas2->PrepareDC(dc);
713  //wxPoint pos = event.GetPosition();
714  _SelectedPoint2.x = dc.DeviceToLogicalX(event.GetX());
715  _SelectedPoint2.y = dc.DeviceToLogicalY(event.GetY());
716  }
717 
718  // update cutout of second image on click or when epipolar line was changed
719  if ((event.GetEventObject() == _ImageCanvas1 && _CutoutFrame2->IsShown()) ||
720  event.GetEventObject() == _ImageCanvas2)
721  {
722  Image<unsigned char> CutoutImage;
723  ComputeCutoutImage(_Image2, CutoutImage,
724  _SelectedPoint2.x - HALF_CUTOUT_SIZE,
725  _SelectedPoint2.y - HALF_CUTOUT_SIZE,
726  CUTOUT_SIZE, CUTOUT_SIZE, SCALE);
727 
728  HomgPoint2D point(_SelectedPoint1.x, _SelectedPoint1.y, 1.0);
729 
730  HomgPoint2D epipole1, epipole2;
731  Matrix3x3<double> CutoutTransform, CutoutTransformInv;
732  CutoutTransform.SetIdentity();
733  CutoutTransform[0][0] = CutoutTransform[1][1] = 1.0 / (double)SCALE;
734  CutoutTransform[0][2] = (double)(_SelectedPoint2.x - HALF_CUTOUT_SIZE);
735  CutoutTransform[1][2] = (double)(_SelectedPoint2.y - HALF_CUTOUT_SIZE);
736 
737  HomgPoint2D endofepipolarline(0,0,0);
738  if (_Projection2.DoesPointProjectIntoImage(pointatinfinity_,
739  endofepipolarline)) {
740 
741  #ifdef BIAS_DEBUG
742  BIASASSERT(CutoutTransform.GetInverse(CutoutTransformInv)==0);
743  #else
744  CutoutTransform.GetInverse(CutoutTransformInv);
745  #endif
746  endofepipolarline = CutoutTransformInv * endofepipolarline;
747  endofepipolarline.Homogenize();
748  int windowsize = 2;
749  if (CutoutImage.IsPositionInImage(int(rint(endofepipolarline[0]))
750  - windowsize,
751  int(rint(endofepipolarline[1]))
752  - windowsize) &&
753  CutoutImage.IsPositionInImage(int(rint(endofepipolarline[0]))
754  + windowsize,
755  int(rint(endofepipolarline[1]))
756  + windowsize)) {
757 
758  // draw the transferred point in PaintedImage2
760  RectangleCenter(CutoutImage,
761  int(rint(endofepipolarline[0])),
762  int(rint(endofepipolarline[1])),
763  windowsize);
764  }
765  } else {
766  BIASERR("Point at infinity does not project into image 2:"
767  <<endofepipolarline);
768  }
769 
770 
771 
772  if (!onlyHomography_) {
773  FMatrix FCutout(P1, P2);
774  FCutout = CutoutTransform.Transpose() * FCutout;
775  FCutout.GetEpipolesHomogenized(epipole1, epipole2);
776  HomgPoint2D::EPosition epos2 =
777  epipole2.DeterminePosition(CUTOUT_SIZE*SCALE, CUTOUT_SIZE*SCALE);
778 
779  // draw epipolar line
780  EpipolarLine eline;
781  eline = FCutout * point;
782  eline.Recalc(CUTOUT_SIZE*SCALE, CUTOUT_SIZE*SCALE, epipole2, epos2);
783 
784 
785  ProjectionParametersBase *pB = _Projection2.GetParameters()->Clone();
786  double cx,cy;
787  Vector3<double> pointOnRay, dirRay;
788  pB->GetPrincipal(cx,cy);
789  cx -= _SelectedPoint2.x - HALF_CUTOUT_SIZE;
790  cy -= _SelectedPoint2.y - HALF_CUTOUT_SIZE;
791  pB->SetPrincipal(cx,cy);
792  pB->SetImageSize(CUTOUT_SIZE,CUTOUT_SIZE);
793  pB->Rescale(1.0/double(SCALE));
794  Projection CutoutProjection(*pB);
795  HomgPoint2D clickedpoint(_SelectedPoint1.x, _SelectedPoint1.y);
796  _Projection1.UnProjectToRay(clickedpoint, pointOnRay, dirRay);
797  EpipolarLine::ProjectEpipolarPlane(CutoutProjection,
798  CutoutImage,
799  _Projection1.GetC(),
800  dirRay,
801  (unsigned char*)NULL,
802  epiLineWidth_
803  );
804  delete pB;
805 
806 
807 
808 
809  }
810 
811  _CutoutFrame2->ShowImage(CutoutImage, _ImageName2);
812  _CutoutFrame2->SetTransform(_SelectedPoint2.x - HALF_CUTOUT_SIZE,
813  _SelectedPoint2.y - HALF_CUTOUT_SIZE, SCALE);
814  _CutoutFrame2->Show(TRUE);
815  _CutoutFrame2->Fit();
816  }
817 }
818 
819 
820 void Usage() {
821  cout<<endl<<"biasshowepiwx is part of the BIAS library."<<endl;
822  cout<<"See www.mip.informatik.uni-kiel.de for new versions."<<endl<<endl;
823  cout<<"Usage: "<<endl;
824  cout<<" biasshowepiwx img1 img2 [projection1 projection2]"<<endl;
825  cout<<endl<<endl;
826  cout<<"This tool loads two images with known camera parameters (intrinsics"
827  <<" and extrinsics) and shows them in a window."
828  <<" Click a point in the left image and you will see the ray in space"
829  <<" projected into the other image (epipolar line). If you have a"
830  <<" fisheye image or an image with radial distortion, the line will"
831  <<" be curved. The camera parameters can be in BIAS::Camera format"
832  <<" within the image meta data (pgm, ppm, mip) or can be given as "
833  <<" separate files on the command line. File formats supported are "
834  <<" those of BIAS::Projection::Load(), namely"<<endl
835  <<" - projection file in xml written by BIAS::Projection::XMLWrite"
836  <<endl
837  <<" - camera parameter file compatible with BIAS::CameraParam class"
838  <<endl
839  <<" - .cam file of BBC's FreeD tracking system"<<endl
840  <<" - projection matrix in .mat file compatible with BIAS::PMatrix"
841  <<endl<<endl;
842  cout<<"The small square shows the vanishing point of the epipolar line "
843  <<" where the feature would lie with pure camera rotation, while the "
844  <<"circle indicates the other end of the epipolar line (the epipole),"
845  <<" which is the projection of the other camera center into the image."
846  <<" Both ends and even the line as a whole may or may not be in the"
847  <<" image, depending on your camera parameters."<<endl
848  <<" Left clicking opens an enlarged window."<<endl;
849 
850 }
851 
852 
853 
854 /*
855 ===============================================================================
856 IntroductionFrame
857 ===============================================================================
858 */
859 enum {
860  ID_SELECT_LEFT_IMAGE = wxID_HIGHEST+188,
861  ID_SELECT_RIGHT_IMAGE,
862  ID_SELECT_LEFT_PROJ,
863  ID_SELECT_RIGHT_PROJ,
864  ID_TEXT_LEFT_IMAGE,
865  ID_TEXT_RIGHT_IMAGE,
866  ID_TEXT_LEFT_PROJ,
867  ID_TEXT_RIGHT_PROJ,
868  ID_BUTTON_OK,
869  ID_BUTTON_CANCEL,
870  ID_STATIC
871 };
872 /** \cond HIDDEN_SYMBOLS */
873 class IntroductionFrame : public wxDialog
874 {
875 public:
876  IntroductionFrame(wxFrame* parent,
877  const wxString& title,
878  const wxPoint& pos,
879  const wxSize& size);
880 
881  void OnButtonLeftImage( wxCommandEvent& event );
882  void OnButtonRightImage( wxCommandEvent& event );
883  void OnButtonLeftProj( wxCommandEvent& event );
884  void OnButtonRightProj( wxCommandEvent& event );
885  void OnButtonOK( wxCommandEvent& event );
886  void OnButtonCancel( wxCommandEvent& event );
887  void SetStrings(wxString* image1,wxString* image2,
888  wxString* proj1,wxString* proj2){
889  image1_ = image1;
890  image2_ = image2;
891  proj1_ = proj1;
892  proj2_ = proj2;
893  };
894 
895 protected:
896  wxTextCtrl *itemTextCtrlLeftP;
897  wxTextCtrl *itemTextCtrlRightP;
898  wxTextCtrl *itemTextCtrlRight;
899  wxTextCtrl *itemTextCtrlLeft;
900  wxString *image1_,*image2_,*proj1_,*proj2_;
901 
902  DECLARE_EVENT_TABLE()
903  DECLARE_CLASS( IntroductionFrame )
904 };
905 /** \endcond */
906 
907 IMPLEMENT_CLASS( IntroductionFrame, wxFrame )
908 
909 BEGIN_EVENT_TABLE(IntroductionFrame, wxDialog)
910  EVT_BUTTON( ID_SELECT_LEFT_IMAGE, IntroductionFrame::OnButtonLeftImage )
911  EVT_BUTTON( ID_SELECT_RIGHT_IMAGE,IntroductionFrame::OnButtonRightImage )
912  EVT_BUTTON( ID_SELECT_LEFT_PROJ, IntroductionFrame::OnButtonLeftProj )
913  EVT_BUTTON( ID_SELECT_RIGHT_PROJ, IntroductionFrame::OnButtonRightProj )
914  EVT_BUTTON( ID_BUTTON_OK, IntroductionFrame::OnButtonOK)
915  EVT_BUTTON( ID_BUTTON_CANCEL, IntroductionFrame::OnButtonCancel)
916 END_EVENT_TABLE()
917 
918 IntroductionFrame::
919 IntroductionFrame(wxFrame* parent,const wxString& title,const wxPoint& pos,const wxSize& size):
920 wxDialog(parent, -1, title, pos, size, wxSTAY_ON_TOP|wxCAPTION|wxRESIZE_BORDER)
921 {
922  // the sizer
923  wxFlexGridSizer* itemFlexGridSizer = new wxFlexGridSizer(3, 0, 0);
924  this->SetSizer(itemFlexGridSizer);
925  wxSize textSize(370,30);
926  ///////////////////////////////////////////////////////////////////////
927  wxStaticText* itemStaticText0 =
928  new wxStaticText( this, ID_STATIC, wxT("First Image"),
929  wxDefaultPosition, wxDefaultSize, 0 );
930  wxButton* itemButtonLeft=new wxButton( this, ID_SELECT_LEFT_IMAGE,
931  wxT("Select"), wxDefaultPosition,
932  wxDefaultSize, 0 );
933  itemTextCtrlLeft = new wxTextCtrl( this, ID_TEXT_LEFT_IMAGE,
934  wxT(""), wxDefaultPosition,
935  textSize, 0 );
936  itemFlexGridSizer->Add(itemStaticText0, 0,
937  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
938  5);
939  itemFlexGridSizer->Add(itemTextCtrlLeft, 0,
940  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
941  5);
942  itemFlexGridSizer->Add(itemButtonLeft, 0,
943  wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
944  ///////////////////////////////////////////////////////////////////////
945  wxStaticText* itemStaticText01 =
946  new wxStaticText( this, ID_STATIC, wxT("Projection"),
947  wxDefaultPosition, wxDefaultSize, 0 );
948  wxButton* itemButtonLeftP=new wxButton( this, ID_SELECT_LEFT_PROJ,
949  wxT("Select"), wxDefaultPosition,
950  wxDefaultSize, 0 );
951  itemTextCtrlLeftP = new wxTextCtrl( this, ID_TEXT_LEFT_PROJ,
952  wxT(""), wxDefaultPosition,
953  textSize, 0 );
954  itemFlexGridSizer->Add(itemStaticText01, 0,
955  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
956  5);
957  itemFlexGridSizer->Add(itemTextCtrlLeftP, 0,
958  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
959  5);
960  itemFlexGridSizer->Add(itemButtonLeftP, 0,
961  wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
962 
963  ///////////////////////////////////////////////////////////////////////
964  wxStaticText* itemStaticText1 =
965  new wxStaticText( this, ID_STATIC, wxT("Second Image"),
966  wxDefaultPosition, wxDefaultSize, 0 );
967  wxButton* itemButtonRight=new wxButton( this, ID_SELECT_RIGHT_IMAGE,
968  wxT("Select"), wxDefaultPosition,
969  wxDefaultSize, 0 );
970  itemTextCtrlRight= new wxTextCtrl( this, ID_TEXT_RIGHT_IMAGE,
971  wxT(""), wxDefaultPosition,
972  textSize, 0 );
973  itemFlexGridSizer->Add(itemStaticText1, 0,
974  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
975  5);
976  itemFlexGridSizer->Add(itemTextCtrlRight, 0,
977  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
978  5);
979  itemFlexGridSizer->Add(itemButtonRight, 0,
980  wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
981  ///////////////////////////////////////////////////////////////////////
982  wxStaticText* itemStaticText02 =
983  new wxStaticText( this, ID_STATIC, wxT("Projection"),
984  wxDefaultPosition, wxDefaultSize, 0 );
985  wxButton* itemButtonRightP=new wxButton( this, ID_SELECT_RIGHT_PROJ,
986  wxT("Select"), wxDefaultPosition,
987  wxDefaultSize, 0 );
988  itemTextCtrlRightP = new wxTextCtrl( this, ID_TEXT_RIGHT_PROJ,
989  wxT(""), wxDefaultPosition,
990  textSize, 0 );
991  itemFlexGridSizer->Add(itemStaticText02, 0,
992  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
993  5);
994  itemFlexGridSizer->Add(itemTextCtrlRightP, 0,
995  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
996  5);
997  itemFlexGridSizer->Add(itemButtonRightP, 0,
998  wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
999  ////////////////////////////////////////////////////////////////////////
1000  wxButton* itemButtonOK = new wxButton( this, ID_BUTTON_OK, _("OK"),
1001  wxDefaultPosition, wxDefaultSize, 0 );
1002  wxButton* itemButtonCancel = new wxButton( this, ID_BUTTON_CANCEL, _("Cancel"),
1003  wxDefaultPosition, wxDefaultSize, 0 );
1004 
1005  itemFlexGridSizer->Add(itemButtonOK, 0,
1006  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
1007  5);
1008  itemFlexGridSizer->Add(itemButtonCancel, 0,
1009  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL,
1010  5);
1011 
1012  ////////////////////////////////////////////////////////////////////
1013  Centre();
1014 }
1015 
1016 void IntroductionFrame::
1017 OnButtonLeftImage( wxCommandEvent& event ){
1018  wxString fileName;
1019  wxFileDialog dialog(this,wxT("Select Image"),wxT(""),wxT(""),
1020  wxT("Images (*.mip;*.pgm;*.ppm;*.jpg;*.png)|*.mip;*.pgm;*.ppm;*.jpg;*.png|All files (*.*)|*.*"),
1021  wxFD_OPEN);
1022  int ret = dialog.ShowModal();
1023  if(ret == wxID_OK){
1024  fileName = dialog.GetPath();
1025  itemTextCtrlLeft->SetValue(fileName);
1026  }
1027  else
1028  return;
1029  }
1030 void IntroductionFrame::
1031 OnButtonRightImage( wxCommandEvent& event ){
1032  wxString fileName;
1033  wxFileDialog dialog(this,wxT("Select Image"),wxT(""),wxT(""),
1034  wxT("Images (*.mip;*.pgm;*.ppm;*.jpg;*.png)|*.mip;*.pgm;*.ppm;*.jpg;*.png|All files (*.*)|*.*"),
1035  wxFD_OPEN);
1036  int ret = dialog.ShowModal();
1037  if(ret == wxID_OK){
1038  fileName = dialog.GetPath();
1039  itemTextCtrlRight->SetValue(fileName);
1040  }
1041  else
1042  return;
1043 }
1044 void IntroductionFrame::
1045 OnButtonLeftProj( wxCommandEvent& event ){
1046  wxString fileName;
1047  wxFileDialog dialog(this,wxT("Select Projection"),wxT(""),wxT(""),
1048  wxT("Projections (*.proj;*.xml)|*.proj;*.xml|All files (*.*)|*.*"),
1049  wxFD_OPEN);
1050  int ret = dialog.ShowModal();
1051  if(ret == wxID_OK){
1052  fileName = dialog.GetPath();
1053  itemTextCtrlLeftP->SetValue(fileName);
1054  }
1055  else
1056  return;
1057 }
1058 void IntroductionFrame::
1059 OnButtonRightProj( wxCommandEvent& event ){
1060  wxString fileName;
1061  wxFileDialog dialog(this,wxT("Select Projection"),wxT(""),wxT(""),
1062  wxT("Projections (*.proj;*.xml)|*.proj;*.xml|All files (*.*)|*.*"),
1063  wxFD_OPEN);
1064  int ret = dialog.ShowModal();
1065  if(ret == wxID_OK){
1066  fileName = dialog.GetPath();
1067  itemTextCtrlRightP->SetValue(fileName);
1068  }
1069  else
1070  return;
1071 }
1072 void IntroductionFrame::
1073 OnButtonOK( wxCommandEvent& event ){
1074  *image1_= itemTextCtrlLeft->GetValue();
1075  *image2_= itemTextCtrlRight->GetValue();
1076  *proj1_= itemTextCtrlLeftP->GetValue();
1077  *proj2_ = itemTextCtrlRightP->GetValue();
1078 
1079  this->Close();
1080 }
1081 void IntroductionFrame::
1082 OnButtonCancel( wxCommandEvent& event ){
1083  exit(0);
1084 }
1085 
1086 /**
1087  * \cond HIDDEN_SYMBOLS
1088  * \class BiasShowEpiApp */
1089 class BiasShowEpiApp : public wxApp
1090 {
1091 public:
1092  virtual bool OnInit();
1093 };
1094 /** \endcond */
1095 
1096 bool BiasShowEpiApp::OnInit()
1097 {
1098  // utility: create a Redirection console for cout, cerr etc.
1100 
1101  // this parameter should be parsed from the command line
1102  bool homographymode = false;
1103  MainFrame* frame = new MainFrame();
1104 
1105  wxString image1,image2, proj1, proj2;
1106  if (argc == 2 && (strcmp(WxToAscii(argv[1]),"-h")==0 ||
1107  strcmp(WxToAscii(argv[1]),"--help")==0 ||
1108  strcmp(WxToAscii(argv[1]),"/?")==0)) {
1109  Usage();
1110 #ifdef WIN32 // avoid closing the window
1111  cout<<"press any key"; _getch();
1112 #endif
1113  return false;
1114  }
1115 
1116  string fileName[2];
1117  string projName[2];
1118  // parse command line
1119  if (argc < 3)
1120  {
1121  Usage();
1122  IntroductionFrame* introframe;
1123  introframe = new IntroductionFrame(NULL,wxT("Select Images and Projections"),wxDefaultPosition,wxSize(600,250));
1124  introframe->SetStrings(&image1,&image2,&proj1, &proj2);
1125  introframe->ShowModal();
1126  fileName[0] = WxToAscii(image1);
1127  fileName[1] = WxToAscii(image2);
1128  projName[0] = WxToAscii(proj1);
1129  projName[1] = WxToAscii(proj2);
1130  }
1131  else{
1132  fileName[0] = WxToAscii(argv[1]);
1133  fileName[1] = WxToAscii(argv[2]);
1134  // use loaded projections, if given
1135  if (argc >= 5)
1136  {
1137  for (int i = 0; i < 2; i++)
1138  {
1139  projName[i] = WxToAscii(argv[i+3]);
1140  }
1141  }
1142  }
1143  // load images
1144  Camera<unsigned char> image[2];
1145  for (int i = 0; i < 2; i++)
1146  {
1147  ImageBase mytmpimg;
1148  if (ImageIO::Load(fileName[i], mytmpimg) != 0)
1149  {
1150  cout << "Failed to load image: " << fileName[i] << endl;
1151  #ifdef WIN32 // avoid closing the window
1152  cout<<"press any key"; _getch();
1153  #endif
1154  return false;
1155  }
1156  cout << "loaded image, storage type is " << mytmpimg.GetStorageType() << endl;
1157  if(mytmpimg.GetStorageType()==ImageBase::ST_float){
1158  Image<float> mytmpFL(mytmpimg);
1159  if(mytmpFL.GetMaxPixelValue() <= 1.0){
1160  mytmpFL.ScaleShift(255, 1.0);
1161  }
1163  } else {
1165  }
1166  image[i].SetMetaData(*mytmpimg.GetMetaData());
1167  image[i].ParseMetaData();
1168  if(projName[i] != ""){
1169  Projection projection;
1170  if (projection.Load(projName[i]) != 0)
1171  {
1172  cout << "Failed to load projection:" << projName[i] << endl;
1173  #ifdef WIN32 // avoid closing the window
1174  cout<<"press any key"; _getch();
1175  #endif
1176  return false;
1177  }
1178  image[i].SetProj(projection);
1179  }
1180  }
1181 
1182  // take projections from images or create them from P matrices
1183  Projection proj[2];
1184  for (int i = 0; i < 2; i++)
1185  {
1186  if (image[i].IsProjValid())
1187  {
1188  proj[i] = image[i].GetProj();
1189  }
1190  else if (image[i].IsPValid())
1191  {
1193  params.SetP(image[i].GetP());
1194  params.SetImageSize(image[i].GetWidth(), image[i].GetHeight());
1195  proj[i] = Projection(params);
1196  }
1197  else
1198  {
1199  cout << "No projection and no P matrix for image: " << fileName[i] << endl;
1200  #ifdef WIN32 // avoid closing the window
1201  cout<<"press any key"; _getch();
1202  #endif
1203  return false;
1204  }
1205 
1206 
1208  dynamic_cast<ProjectionParametersPerspective* >(proj[i].GetParameters());
1209  if (pPPP!=NULL) {
1210  // have perspective cam, avoid ugly distortion double overflow!
1211  pPPP->UpdateMinZLocal();
1212  }
1213  }
1214 
1215  // convert images to RGB
1216  Image<unsigned char> rgbImage[2];
1217  if (ImageConvert::ToRGB(image[0], rgbImage[0]) != 0 ||
1218  ImageConvert::ToRGB(image[1], rgbImage[1]) != 0)
1219  {
1220  cout << "Failed to convert images to RGB" << endl;
1221  #ifdef WIN32 // avoid closing the window
1222  cout<<"press any key"; _getch();
1223  #endif
1224  return false;
1225  }
1226 
1227 
1228  // show frame
1229  frame->Show(TRUE);
1230  frame->SetImages(rgbImage[0], proj[0], fileName[0],
1231  rgbImage[1], proj[1], fileName[1], homographymode);
1232  SetTopWindow(frame);
1233 
1234  return TRUE;
1235 }
1236 
1237 IMPLEMENT_APP(BiasShowEpiApp)
virtual BIAS::KMatrix GetFakeKMatrix(double &imgsize, int resolution=0, const double &maxangle=1.4) const
Returns a fake KMatrix for the camera.
virtual BIAS::Vector3< double > GetC() const
Get projection center.
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
virtual HomgPoint2D ProjectLocal(const Vector3< double > &point, bool IgnoreDistortion=false) const
calculates the projection of a point in the camera coordinate system to a pixel in the image plane of...
int Recalc(unsigned int width, unsigned int height, HomgPoint2D &epipole, enum HomgPoint2D::EPosition epos)
assumes that data_ is already set
virtual void SetPrincipal(const double x, const double y)
Set principal point (in pixels relative to top left corner).
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
virtual int Load(const std::string &filename)
convenience wrapper which tries to read different formats
Definition: Projection.cpp:62
enum EPosition DeterminePosition(unsigned int width, unsigned int height)
Definition: HomgPoint2D.hh:403
void BIASGui_EXPORT ConsoleRedirectIO(std::string name=std::string(""))
Extra Console for WIN32 WinMain gui applications.
wxString AsciiToWx(const char *thestring)
Converts a C string to a wxString.
Definition: StringConv.hh:32
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual int GetPrincipal(double &PrincipalX, double &PrincipalY) const
Get principal point (in pixels relative to top left corner).
bool IsPositionInImage(const int &x, const int &y) const
check if image contains that pixel position
Definition: ImageBase.hh:110
virtual void SetImageSize(const unsigned int w, const unsigned int h)
Set image dimensions (in pixels).
virtual ProjectionParametersBase * Clone() const =0
Covariant virtual copy constructor used in BIAS::Projection.
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
MetaData * GetMetaData()
Definition: ImageBase.hh:456
float image storage type
Definition: ImageBase.hh:118
virtual void SetP(const PMatrix &P)
set from P
unsigned int GetWidth() const
Definition: ImageBase.hh:312
virtual HomgPoint2D ProjectLocal(const Vector3< double > &point, bool IgnoreDistortion=false) const
calculates the projection of a point in the local camera coordinate system to a pixel in the image pl...
static int CircleCenter(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[]=NULL)
draws a circular line, either using Value or a good contrast value
Definition: ImageDraw.cpp:977
virtual void SetQ(const BIAS::Quaternion< double > &Q)
Set orientation from unit quaternion Q.
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
Definition: Vector3.hh:594
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
Image canvas that does not show zoom frames and redirects mouse click events to its parent...
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
Definition: Matrix3x3.cpp:373
int SetProj(const Projection &Proj)
Definition: Camera.hh:106
class representing a Fundamental matrix
Definition: FMatrix.hh:46
unsigned int GetHeight() const
Definition: ImageBase.hh:319
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
virtual bool DoesPointProjectIntoImage(const BIAS::HomgPoint3D &X, BIAS::HomgPoint2D &x, unsigned int cam=0, bool IgnoreDistortion=false) const
Checks if 3D point projects into specified image and returns belonging 2D image point.
Definition: Projection.cpp:300
static int RectangleCenter(Image< StorageType > &im, const int x, const int y, const int size, const StorageType value[])
Draws the rectangle around X, Y with Size and Value[i] in channel i.
Definition: ImageDraw.cpp:284
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
virtual bool Undistort(BIAS::HomgPoint2D &point2d) const
Using the Matlab camera calibration toolbox parameters for an undistortion of distorted coordinates...
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Definition: Matrix3x3.cpp:167
static void ProjectEpipolarPlane(const Projection &thisP, Image< PixelType > &thisIm, const Vector3< double > &otherCamCenter, const Vector3< double > &RayDir, PixelType *Color=NULL, int lineWidth=1)
visualize the epipolar plane/line as a curve in the image for any Projection
void UpdateMinZLocal()
run along image border and compute maximum field of view, save in minzlocal
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
double GetRadius() const
Return radius of spherical image in pixels.
void SetMetaData(const MetaData &m)
Definition: ImageBase.hh:470
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
const BIAS::Projection & GetProj() const
Definition: Camera.hh:109
virtual BIAS::Quaternion< double > GetQ() const
Get orientation as unit quaternion.
Vector3< double > GetC(unsigned int cam=0) const
return Center of camera with index cam.
Definition: Projection.hh:236
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
virtual void SetK(const KMatrix &K)
sets the internal parameters from a given KMatrix and updates the cached K and its inverse ...
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
virtual void SetC(const BIAS::Vector3< double > &C)
Set projection center.
int ParseMetaData(bool bUse2x64bitTS=true)
After ImageIO::Load() operated on AppData_, this method fills P_, Timestamp, DC_*, ...
Definition: Camera.cpp:154
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
class BIASGeometryBase_EXPORT HomgPoint2D
class BIASGeometryBase_EXPORT HomgPoint3D
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429
A class for representing epipolar lines with useful functions like ScanLine().
Definition: EpipolarLine.hh:69
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153