Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LensCalFrame.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /*
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This software is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public
23  * License along with this software. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  */
27 
28 #include "panoinc_WX.h"
29 #include "panoinc.h"
30 
31 #include "base_wx/platform.h"
32 #include "base_wx/wxPlatform.h"
33 #include "base_wx/LensTools.h"
34 #include "base_wx/GraphTools.h"
35 #include "huginapp/ImageCache.h"
36 #include "LensCalFrame.h"
37 #include <wx/app.h>
38 #include "LensCalApp.h"
39 #include "hugin/config_defaults.h"
41 #include "lensdb/LensDB.h"
42 #include "base_wx/wxLensDB.h"
44 
45 const unsigned int cps_per_line=10;
46 
47 #define DEFAULT_LENSCAL_SCALE 2.0
48 #define DEFAULT_LENSCAL_THRESHOLD 4.0
49 #define DEFAULT_RESIZE_DIMENSION 1600
50 #define DEFAULT_MINLINELENGTH 0.3
51 
53 bool FileDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
54 {
55  DEBUG_TRACE("OnDropFiles");
56  LensCalFrame* frame=wxGetApp().GetLensCalFrame();
57  if (!frame)
58  return false;
59 
60  // try to add as images
61  wxArrayString files;
62  wxArrayString invalidFiles;
63  for (unsigned int i=0; i< filenames.GetCount(); i++)
64  {
65  wxFileName file(filenames[i]);
66  if (file.GetExt().CmpNoCase(wxT("jpg")) == 0 ||
67  file.GetExt().CmpNoCase(wxT("jpeg")) == 0 ||
68  file.GetExt().CmpNoCase(wxT("tif")) == 0 ||
69  file.GetExt().CmpNoCase(wxT("tiff")) == 0 ||
70  file.GetExt().CmpNoCase(wxT("png")) == 0 ||
71  file.GetExt().CmpNoCase(wxT("bmp")) == 0 ||
72  file.GetExt().CmpNoCase(wxT("gif")) == 0 ||
73  file.GetExt().CmpNoCase(wxT("pnm")) == 0 ||
74  file.GetExt().CmpNoCase(wxT("sun")) == 0 ||
75  file.GetExt().CmpNoCase(wxT("hdr")) == 0 ||
76  file.GetExt().CmpNoCase(wxT("viff")) == 0 )
77  {
78  if(containsInvalidCharacters(file.GetFullPath()))
79  {
80  invalidFiles.push_back(file.GetFullPath());
81  }
82  else
83  {
84  files.push_back(file.GetFullPath());
85  };
86  }
87  }
88  if(!invalidFiles.empty())
89  {
90  ShowFilenameWarning(frame, invalidFiles);
91  }
92  // we got some images to add.
93  if (!files.empty())
94  {
95  // use a Command to ensure proper undo and updating of GUI parts
96  frame->AddImages(files);
97  }
98  return true;
99 }
100 
101 // event table. this frame will recieve mostly global commands.
102 BEGIN_EVENT_TABLE(LensCalFrame, wxFrame)
103  EVT_LISTBOX(XRCID("lenscal_images_list"), LensCalFrame::OnImageSelected)
104  EVT_MENU(XRCID("menu_save"), LensCalFrame::OnSaveProject)
105  EVT_MENU(XRCID("menu_quit"), LensCalFrame::OnExit)
106  EVT_BUTTON(XRCID("lenscal_add_image"), LensCalFrame::OnAddImage)
107  EVT_BUTTON(XRCID("lenscal_remove_image"), LensCalFrame::OnRemoveImage)
108  EVT_BUTTON(XRCID("lenscal_find_lines"), LensCalFrame::OnFindLines)
109  EVT_BUTTON(XRCID("lenscal_reset"), LensCalFrame::OnReset)
110  EVT_BUTTON(XRCID("lenscal_opt"), LensCalFrame::OnOptimize)
111  EVT_BUTTON(XRCID("lenscal_show_distortion_graph"), LensCalFrame::OnShowDistortionGraph)
112  EVT_BUTTON(XRCID("lenscal_save_lens"), LensCalFrame::OnSaveLens)
113  EVT_BUTTON(XRCID("lenscal_refresh"), LensCalFrame::OnRefresh)
114  EVT_CHOICE(XRCID("lenscal_preview_content"), LensCalFrame::OnSelectPreviewContent)
115  EVT_CHECKBOX(XRCID("lenscal_show_lines"), LensCalFrame::OnShowLines)
117 
118 LensCalFrame::LensCalFrame(wxWindow* parent)
119 {
120  DEBUG_TRACE("");
121  // load our children. some children might need special
122  // initialization. this will be done later.
123  wxXmlResource::Get()->LoadFrame(this, parent, wxT("lenscal_frame"));
124  DEBUG_TRACE("");
125 
126  // load our menu bar
127 #ifdef __WXMAC__
128  wxApp::s_macExitMenuItemId = XRCID("menu_quit");
129 #endif
130  SetMenuBar(wxXmlResource::Get()->LoadMenuBar(this, wxT("lenscal_menubar")));
131 
132  m_choice_projection=XRCCTRL(*this,"lenscal_proj_choice",wxChoice);
133  FillLensProjectionList(m_choice_projection);
134  m_images_list=XRCCTRL(*this,"lenscal_images_list",wxListBox);
135  m_preview=XRCCTRL(*this,"lenscal_preview",LensCalImageCtrl);
136 
137  wxConfigBase* config = wxConfigBase::Get();
138  config->Read(wxT("/LensCalFrame/EdgeScale"),&m_edge_scale,DEFAULT_LENSCAL_SCALE);
139  config->Read(wxT("/LensCalFrame/EdgeThreshold"),&m_edge_threshold,DEFAULT_LENSCAL_THRESHOLD);
140  m_resize_dimension=config->Read(wxT("/LensCalFrame/ResizeDimension"),DEFAULT_RESIZE_DIMENSION);
141  config->Read(wxT("/LensCalFrame/MinLineLength"),&m_minlinelength,DEFAULT_MINLINELENGTH);
142  ParametersToDisplay();
143 
144  bool selected;
145  config->Read(wxT("/LensCalFrame/Optimize_a"),&selected,false);
146  XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->SetValue(selected);
147  config->Read(wxT("/LensCalFrame/Optimize_b"),&selected,true);
148  XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->SetValue(selected);
149  config->Read(wxT("/LensCalFrame/Optimize_c"),&selected,false);
150  XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->SetValue(selected);
151  config->Read(wxT("/LensCalFrame/Optimize_de"),&selected,false);
152  XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->SetValue(selected);
153 
154  // set the minimize icon
155 #ifdef __WXMSW__
156  wxIconBundle myIcons(GetXRCPath() + wxT("data/hugin.ico"), wxBITMAP_TYPE_ICO);
157  SetIcons(myIcons);
158 #else
159  wxIcon myIcon(GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
160  SetIcon(myIcon);
161 #endif
162  SetTitle(_("Hugin Lens calibration GUI"));
163 
164  // create a new drop handler. wxwindows deletes the automatically
165  SetDropTarget(new FileDropTarget());
166 
167  // create a status bar
168  const int fields (2);
169  CreateStatusBar(fields);
170  int widths[fields] = {-1, 85};
171  SetStatusWidths( fields, &widths[0]);
172 
173  // Set sizing characteristics
174  //set minumum size
175 #if defined __WXMAC__ || defined __WXMSW__
176  // a minimum nice looking size; smaller than this would clutter the layout.
177  SetSizeHints(900, 675);
178 #else
179  // For ASUS eeePc
180  SetSizeHints(780, 455); //set minumum size
181 #endif
182 
183  // set progress display for image cache.
184  ImageCache::getInstance().setProgressDisplay(this);
185 #if defined __WXMSW__
186  unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
187  unsigned long mem_low = config->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
188  unsigned long mem_high = config->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
189  if (mem_high > 0) {
190  mem = ((unsigned long long) mem_high << 32) + mem_low;
191  }
192  else {
193  mem = mem_low;
194  }
195  ImageCache::getInstance().SetUpperLimit(mem);
196 #else
197  ImageCache::getInstance().SetUpperLimit(config->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
198 #endif
199  //disable buttons
200  EnableButtons();
201  XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(false);
202 }
203 
205 {
206  DEBUG_TRACE("dtor");
208  ImageCache::getInstance().setProgressDisplay(0);
209  delete & ImageCache::getInstance();
210  // get the global config object
211  wxConfigBase* config = wxConfigBase::Get();
212  if(ReadInputs(false,true,false))
213  {
214  config->Write(wxT("/LensCalFrame/EdgeScale"),m_edge_scale);
215  config->Write(wxT("/LensCalFrame/EdgeThreshold"),m_edge_threshold);
216  config->Write(wxT("/LensCalFrame/ResizeDimension"),(int)m_resize_dimension);
217  config->Write(wxT("/LensCalFrame/MinLineLength"),m_minlinelength);
218  };
219  config->Write(wxT("/LensCalFrame/Optimize_a"),XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue());
220  config->Write(wxT("/LensCalFrame/Optimize_b"),XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue());
221  config->Write(wxT("/LensCalFrame/Optimize_c"),XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue());
222  config->Write(wxT("/LensCalFrame/Optimize_de"),XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue());
223  StoreFramePosition(this, wxT("LensCalFrame"));
224  config->Flush();
225  //cleanup
226  for(unsigned int i=0;i<m_images.size();i++)
227  {
228  delete m_images[i];
229  };
230  m_images.clear();
232  DEBUG_TRACE("dtor end");
233 }
234 
236 {
237  XRCCTRL(*this,"lenscal_scale",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_scale,2));
238  XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_threshold, 2));
239  XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->SetValue(wxString::Format(wxT("%d"), m_resize_dimension));
240  XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_minlinelength, 2));
241 };
242 
243 const wxString & LensCalFrame::GetXRCPath()
244 {
245  return wxGetApp().GetXRCPath();
246 };
247 
250 {
251  wxString msg;
252  if (!m_message.empty())
253  {
254  msg = wxGetTranslation(wxString(m_message.c_str(), wxConvLocal));
255  if (!m_filename.empty())
256  {
257  msg.Append(wxT(" "));
258  msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
259  };
260  };
261  GetStatusBar()->SetStatusText(msg, 0);
262 
263 #ifdef __WXMSW__
264  UpdateWindow(NULL);
265 #endif
266 }
267 
268 void LensCalFrame::OnExit(wxCommandEvent &e)
269 {
270  Close();
271 };
272 
273 void LensCalFrame::AddImages(wxArrayString files)
274 {
275  wxArrayString wrongSize;
276  wxArrayString wrongExif;
277  for (unsigned int i=0; i<files.GetCount(); i++)
278  {
279  ImageLineList* image=new ImageLineList(files[i]);
280  //check input
281  {
282  // check for black/white images
283  const HuginBase::FileMetaData metadata = image->GetPanoImage()->getFileMetadata();
284  HuginBase::FileMetaData::const_iterator it = metadata.find("pixeltype");
285  if (it != metadata.end())
286  {
287  if (it->second == "BILEVEL")
288  {
289  wxMessageBox(wxString::Format(_("File \"%s\" is a black/white image.\nHugin does not support this image type. Skipping this image.\nConvert image to grayscale image and try loading again."), files[i].c_str()),
290  _("Warning"), wxOK | wxICON_EXCLAMATION, this);
291  delete image;
292  continue;
293  };
294  };
295  };
296  if(!m_images.empty())
297  {
298  const HuginBase::SrcPanoImage* image0=m_images[0]->GetPanoImage();
299  const HuginBase::SrcPanoImage* image1=image->GetPanoImage();
300  if(image0->getSize()!=image1->getSize())
301  {
302  wrongSize.push_back(files[i]);
303  delete image;
304  continue;
305  };
306  if(!image0->getExifMake().empty() && !image1->getExifMake().empty() &&
307  !image0->getExifModel().empty() && !image1->getExifModel().empty() &&
308  image0->getExifFocalLength()>0 && image1->getExifFocalLength()>0 &&
309  image0->getCropFactor()>0 && image1->getCropFactor()>0
310  )
311  {
312  if(image0->getExifMake()!=image1->getExifMake() ||
313  image0->getExifModel()!=image1->getExifModel() ||
314  image0->getExifFocalLength()!=image1->getExifFocalLength() ||
315  image0->getCropFactor()!=image1->getCropFactor())
316  {
317  //only show a warning, but continue processing
318  wrongExif.push_back(files[i]);
319  };
320  };
321  };
322  m_images.push_back(image);
323  SetStatusText(wxString::Format(_("Added %s"),image->GetFilename().c_str()));
324  if (image->GetPanoImage()->getExifFocalLength() > 0)
325  {
326  XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->SetValue(
327  hugin_utils::doubleTowxString(image->GetPanoImage()->getExifFocalLength(), 2)
328  );
329  };
330  if (image->GetPanoImage()->getExifCropFactor() > 0)
331  {
332  XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->SetValue(
333  hugin_utils::doubleTowxString(image->GetPanoImage()->getCropFactor(), 2)
334  );
335  };
336  SelectListValue(m_choice_projection,image->GetPanoImage()->getProjection());
337  }
338  UpdateList(false);
339  m_images_list->SetSelection(m_images_list->GetCount()-1);
340  wxCommandEvent e;
341  OnImageSelected(e);
342  EnableButtons();
343  if(!wrongSize.empty())
344  {
345  wxString fileText;
346  for(unsigned int i=0;i<wrongSize.size();i++)
347  {
348  wxFileName filename(wrongSize[i]);
349  fileText.Append(filename.GetFullName());
350  if(i<wrongSize.size()-1)
351  fileText.Append(wxT(", "));
352  };
353  wxMessageBox(wxString::Format(_("The size of the images (%s) does not match the already added image(s)."),fileText.c_str()),
354  _("Error"),wxOK|wxICON_EXCLAMATION,this);
355  };
356  if(!wrongExif.empty())
357  {
358  wxString fileText;
359  for(unsigned int i=0;i<wrongExif.size();i++)
360  {
361  wxFileName filename(wrongExif[i]);
362  fileText.Append(filename.GetFullName());
363  if(i<wrongExif.size()-1)
364  fileText.Append(wxT(", "));
365  };
366  wxMessageBox(wxString::Format(_("The EXIF information of the added images (%s) is not consistent with the already added image(s).\nPlease check the image again, if you selected the correct images."),fileText.c_str()),
367  _("Warning"),wxOK|wxICON_EXCLAMATION,this);
368  };
369 };
370 
371 void LensCalFrame::OnAddImage(wxCommandEvent &e)
372 {
373  wxConfigBase* config = wxConfigBase::Get();
374  wxString path = config->Read(wxT("/actualPath"), wxT(""));
375  wxFileDialog dlg(this,_("Add images"),
376  path, wxT(""),
378  wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST | wxFD_PREVIEW, wxDefaultPosition);
379  dlg.SetDirectory(path);
380 
381  // remember the image extension
382  wxString img_ext;
383  if (config->HasEntry(wxT("lastImageType"))){
384  img_ext = config->Read(wxT("lastImageType")).c_str();
385  }
386  if (img_ext == wxT("all images"))
387  dlg.SetFilterIndex(0);
388  else if (img_ext == wxT("jpg"))
389  dlg.SetFilterIndex(1);
390  else if (img_ext == wxT("tiff"))
391  dlg.SetFilterIndex(2);
392  else if (img_ext == wxT("png"))
393  dlg.SetFilterIndex(3);
394  else if (img_ext == wxT("hdr"))
395  dlg.SetFilterIndex(4);
396  else if (img_ext == wxT("exr"))
397  dlg.SetFilterIndex(5);
398  else if (img_ext == wxT("all files"))
399  dlg.SetFilterIndex(6);
400  DEBUG_INFO ( "Image extention: " << img_ext.mb_str(wxConvLocal) )
401 
402  // call the file dialog
403  if (dlg.ShowModal() == wxID_OK)
404  {
405  // get the selections
406  wxArrayString Pathnames;
407  dlg.GetPaths(Pathnames);
408 
409  // save the current path to config
410 #ifdef __WXGTK__
411  //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
412  config->Write(wxT("/actualPath"), wxPathOnly(Pathnames[0]));
413 #else
414  config->Write(wxT("/actualPath"), dlg.GetDirectory());
415 #endif
416 
417  wxArrayString invalidFiles;
418  for(unsigned int i=0;i<Pathnames.GetCount(); i++)
419  {
420  if(containsInvalidCharacters(Pathnames[i]))
421  {
422  invalidFiles.push_back(Pathnames[i]);
423  };
424  };
425  if(!invalidFiles.empty())
426  {
427  ShowFilenameWarning(this, invalidFiles);
428  }
429  else
430  {
431  AddImages(Pathnames);
432  };
433  DEBUG_INFO ( wxString::Format(wxT("img_ext: %d"), dlg.GetFilterIndex()).mb_str(wxConvLocal) )
434  // save the image extension
435  switch ( dlg.GetFilterIndex() )
436  {
437  case 0: config->Write(wxT("lastImageType"), wxT("all images")); break;
438  case 1: config->Write(wxT("lastImageType"), wxT("jpg")); break;
439  case 2: config->Write(wxT("lastImageType"), wxT("tiff")); break;
440  case 3: config->Write(wxT("lastImageType"), wxT("png")); break;
441  case 4: config->Write(wxT("lastImageType"), wxT("hdr")); break;
442  case 5: config->Write(wxT("lastImageType"), wxT("exr")); break;
443  case 6: config->Write(wxT("lastImageType"), wxT("all files")); break;
444  }
445  }
446  else
447  {
448  // nothing to open
449  SetStatusText( _("Add Image: cancel"));
450  }
451  EnableButtons();
452 };
453 
454 void LensCalFrame::UpdateListString(unsigned int index)
455 {
456  wxFileName file(m_images[index]->GetFilename());
457  m_images_list->SetString(index,wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[index]->GetNrOfValidLines()));
458 };
459 
460 void LensCalFrame::UpdateList(bool restoreSelection)
461 {
462  int oldSelection=m_images_list->GetSelection();
463  m_images_list->Clear();
464  for(unsigned int i=0;i<m_images.size();i++)
465  {
466  wxFileName file(m_images[i]->GetFilename());
467  wxString text=wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[i]->GetNrOfValidLines());
468  m_images_list->Append(text);
469  };
470  if(oldSelection!=wxNOT_FOUND && restoreSelection)
471  {
472  m_images_list->SetSelection(oldSelection);
473  };
474  wxCommandEvent e;
475  OnImageSelected(e);
476 };
477 
478 void LensCalFrame::OnRemoveImage(wxCommandEvent &e)
479 {
480  int selection=m_images_list->GetSelection();
481  if(selection!=wxNOT_FOUND)
482  {
483  // remove file from cache
484  const std::string filename(m_images[selection]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
485  ImageCache::getInstance().removeImage(filename);
486  delete m_images[selection];
487  m_images.erase(m_images.begin()+selection);
488  UpdateList(false);
489  }
490  else
491  {
492  wxBell();
493  };
494  EnableButtons();
495 };
496 
498 {
499  const bool enabling = !m_images.empty();
500  XRCCTRL(*this,"lenscal_find_lines",wxButton)->Enable(enabling);
501  XRCCTRL(*this,"lenscal_opt",wxButton)->Enable(enabling);
502  XRCCTRL(*this, "lenscal_show_distortion_graph", wxButton)->Enable(enabling);
503  XRCCTRL(*this,"lenscal_save_lens",wxButton)->Enable(enabling);
504  GetMenuBar()->Enable(XRCID("menu_save"),enabling);
505 };
506 
507 bool LensCalFrame::ReadInputs(bool readFocalLength,bool readOptions,bool readLensParameter)
508 {
509  if(readFocalLength)
510  {
512  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->GetValue(), m_focallength))
513  return false;
514  if(m_focallength<1)
515  return false;
516  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->GetValue(), m_cropfactor))
517  return false;
518  if(m_cropfactor<0.1)
519  return false;
520  }
521  if(readOptions)
522  {
523  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_scale", wxTextCtrl)->GetValue(), m_edge_scale))
524  return false;
525  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->GetValue(), m_edge_threshold))
526  return false;
527  double resize_dim;
528  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->GetValue(), resize_dim))
529  return false;
530  if(resize_dim<100)
531  return false;
532  m_resize_dimension=(unsigned int)resize_dim;
533  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->GetValue(), m_minlinelength))
534  return false;
535  if(m_minlinelength<=0 || m_minlinelength>1)
536  return false;
537  };
538  if(readLensParameter)
539  {
540  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_a", wxTextCtrl)->GetValue(), m_a))
541  return false;
542  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_b", wxTextCtrl)->GetValue(), m_b))
543  return false;
544  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_c", wxTextCtrl)->GetValue(), m_c))
545  return false;
546  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_d", wxTextCtrl)->GetValue(), m_d))
547  return false;
548  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_e", wxTextCtrl)->GetValue(), m_e))
549  return false;
550  }
551  return true;
552 };
553 
554 void LensCalFrame::OnFindLines(wxCommandEvent &e)
555 {
556  if(!ReadInputs(true,true,false))
557  {
558  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
559  return;
560  }
562  for(unsigned int i=0;i<m_images.size();i++)
563  {
564  std::string filename(m_images[i]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
565  ImageCache::EntryPtr img=ImageCache::getInstance().getImage(filename);
566  double scale;
567  SetStatusText(_("Detecting edges..."));
568  m_images[i]->SetEdgeImage(HuginLines::detectEdges(*(img->get8BitImage()),m_edge_scale,m_edge_threshold,m_resize_dimension,scale));
569  SetStatusText(_("Finding lines..."));
571  m_images[i]->ScaleLines(scale);
572  };
573  SetStatusText(_("Finished"));
574  UpdateList(true);
575 };
576 
577 void LensCalFrame::OnOptimize(wxCommandEvent &e)
578 {
579  if(!ReadInputs(true,false,true))
580  {
581  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
582  return;
583  }
584  unsigned int count=0;
585  for(unsigned int i=0;i<m_images.size();i++)
586  count+=m_images[i]->GetNrOfValidLines();
587  if(count==0)
588  {
589  wxMessageBox(_("There are no detected lines.\nPlease run \"Find lines\" first. If there are no lines found, change the parameters."),_("Warning"),wxOK | wxICON_INFORMATION, this);
590  return;
591  };
592  Optimize();
593 };
594 
595 void LensCalFrame::OnShowDistortionGraph(wxCommandEvent &e)
596 {
597  if (m_images.empty())
598  {
599  return;
600  };
601  if (!ReadInputs(true, false, true))
602  {
603  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Warning"), wxOK | wxICON_INFORMATION, this);
604  return;
605  };
606  delete m_popup;
607  HuginBase::SrcPanoImage image(*(m_images[0]->GetPanoImage()));
608  image.setProjection(m_projection);
609  image.setExifFocalLength(m_focallength);
610  image.setCropFactor(m_cropfactor);
611  image.setVar("a", m_a);
612  image.setVar("b", m_b);
613  image.setVar("c", m_c);
614  image.setVar("d", m_d);
615  image.setVar("e", m_e);
616  image.setHFOV(HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize()));
617 
619  wxWindow *button = (wxWindow*)e.GetEventObject();
620  wxPoint pos = button->ClientToScreen(wxPoint(0, 0));
621  m_popup->Position(pos, button->GetSize());
622  m_popup->Popup();
623 };
624 
626 {
627  HuginBase::Panorama pano;
629  unsigned int line_number=3;
630  for(unsigned int i=0;i<m_images.size();i++)
631  {
632  HuginBase::SrcPanoImage image(*(m_images[i]->GetPanoImage()));
633  image.setProjection(m_projection);
634  image.setExifFocalLength(m_focallength);
635  image.setCropFactor(m_cropfactor);
636  image.setVar("a",m_a);
637  image.setVar("b",m_b);
638  image.setVar("c",m_c);
639  image.setVar("d",m_d);
640  image.setVar("e",m_e);
641  double hfov = HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize());
642  image.setHFOV(hfov);
643  pano.addImage(image);
644  std::set<std::string> imgopt;
645  if(i==0)
646  {
647  if(XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue())
648  imgopt.insert("a");
649  if(XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue())
650  imgopt.insert("b");
651  if(XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue())
652  imgopt.insert("c");
653  if(XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue())
654  {
655  imgopt.insert("d");
656  imgopt.insert("e");
657  }
658  };
659  optvec.push_back(imgopt);
660  //now generate control points from lines
661  HuginLines::Lines lines=m_images[i]->GetLines();
662  for(unsigned j=0;j<lines.size();j++)
663  {
664  if(lines[j].status==HuginLines::valid_line)
665  {
666  HuginBase::CPVector cpv=GetControlPoints(lines[j],i,line_number,cps_per_line);
667  for(unsigned int k=0;k<cpv.size();k++)
668  pano.addCtrlPoint(cpv[k]);
669  line_number++;
670  };
671  };
672  };
673  //assign all images the same lens number
674  HuginBase::StandardImageVariableGroups variable_groups(pano);
675  HuginBase::ImageVariableGroup & lenses = variable_groups.getLenses();
676  if(pano.getNrOfImages()>1)
677  {
678  for(unsigned int i=1;i<pano.getNrOfImages();i++)
679  {
680  HuginBase::SrcPanoImage img = pano.getSrcImage(i);
681  lenses.switchParts(i,lenses.getPartNumber(0));
682  img.setExposureValue(0);
683  img.setWhiteBalanceRed(1);
684  img.setWhiteBalanceBlue(1);
685  pano.setSrcImage(i, img);
686  };
687  };
688  //set default exposure value
690  opts.outputExposureValue = 0;
692  pano.setOptions(opts);
693 
694  pano.setOptimizeVector(optvec);
695  return pano;
696 };
697 
699 {
700  SetStatusText(_("Optimizing lens distortion parameters..."));
703 
704  const HuginBase::SrcPanoImage img = pano.getImage(0);
705  m_a=img.getVar("a");
706  m_b=img.getVar("b");
707  m_c=img.getVar("c");
708  m_d=img.getVar("d");
709  m_e=img.getVar("e");
710  XRCCTRL(*this,"lenscal_a",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_a,5));
711  XRCCTRL(*this,"lenscal_b",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_b,5));
712  XRCCTRL(*this,"lenscal_c",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_c,5));
713  XRCCTRL(*this,"lenscal_d",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_d,3));
714  XRCCTRL(*this,"lenscal_e",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_e,3));
716  SetStatusText(_("Finished"));
717 };
718 
720 {
721  wxFileDialog dlg(this,
722  _("Save lens parameters file"),
723  wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
724  _("Lens Project Files (*.ini)|*.ini|All files (*)|*"),
725  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
726  dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")));
727  if (dlg.ShowModal() == wxID_OK)
728  {
729  wxFileName filename(dlg.GetPath());
730  if(!filename.HasExt())
731  filename.SetExt(wxT("ini"));
732  wxConfig::Get()->Write(wxT("/lensPath"), dlg.GetDirectory()); // remember for later
733  if (filename.FileExists())
734  {
735  int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), filename.GetFullPath().c_str()),
736  _("Save project"), wxYES_NO | wxICON_QUESTION);
737  if (d != wxYES)
738  {
739  return;
740  }
741  }
743  SaveLensParameters(filename.GetFullPath(),&pano,0);
744  }
745 };
746 
747 void LensCalFrame::OnSaveLens(wxCommandEvent &e)
748 {
749  if(!ReadInputs(true,false,true))
750  {
751  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
752  return;
753  }
754  unsigned int count=0;
755  for(unsigned int i=0;i<m_images.size();i++)
756  count+=m_images[i]->GetNrOfValidLines();
757  if(count==0)
758  {
759  wxMessageBox(_("There are no detected lines.\nPlease run \"Find lines\" and \"Optimize\" before saving the lens data. If there are no lines found, change the parameters."),_("Warning"),wxOK | wxICON_INFORMATION, this);
760  return;
761  };
762 
763  wxArrayString choices;
764  choices.push_back(_("Save lens parameters to ini file"));
765  choices.push_back(_("Save lens parameters to lens database"));
766  wxSingleChoiceDialog save_dlg(this,_("Saving lens data"),_("Save lens"),choices);
767  if(save_dlg.ShowModal()==wxID_OK)
768  {
769  if(save_dlg.GetSelection()==0)
770  {
771  SaveLensToIni();
772  }
773  else
774  {
776  SaveLensParameters(this,pano.getImage(0),false);
777  };
778  };
779 };
780 
781 void LensCalFrame::OnSaveProject(wxCommandEvent &e)
782 {
783  if(!ReadInputs(true,false,true))
784  {
785  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
786  return;
787  }
788 
789  wxFileDialog dlg(this,_("Save project file"),wxEmptyString,wxEmptyString,
790  _("Project files (*.pto)|*.pto|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
791  dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
792  if (dlg.ShowModal() == wxID_OK)
793  {
794  wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory()); // remember for later
795  wxFileName filename(dlg.GetPath());
796  if(!filename.HasExt())
797  filename.SetExt(wxT("pto"));
798  if (filename.FileExists())
799  {
800  int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), filename.GetFullPath().c_str()),
801  _("Save project"), wxYES_NO | wxICON_QUESTION);
802  if (d != wxYES)
803  {
804  return;
805  }
806  }
808  const std::string output(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
809  pano.WritePTOFile(output, hugin_utils::getPathPrefix(output));
810  };
811 };
812 
813 void LensCalFrame::OnImageSelected(wxCommandEvent &e)
814 {
815  bool selected=m_images_list->GetSelection()!=wxNOT_FOUND;
816  XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(selected);
817  if(selected)
818  {
819  m_preview->SetImage(m_images[m_images_list->GetSelection()],m_images_list->GetSelection());
820  }
821  else
822  {
824  };
825 };
826 
828 {
830  XRCCTRL(*this,"lenscal_refresh",wxButton)->Enable(m_preview->GetMode()==LensCalImageCtrl::mode_corrected);
831 };
832 
833 void LensCalFrame::OnShowLines(wxCommandEvent &e)
834 {
835  m_preview->SetShowLines(XRCCTRL(*this,"lenscal_show_lines",wxCheckBox)->GetValue());
836  m_preview->Refresh(true);
837 };
838 
839 void LensCalFrame::OnReset(wxCommandEvent &e)
840 {
846 };
847 
848 void LensCalFrame::OnRefresh(wxCommandEvent &e)
849 {
850  if(!ReadInputs(true,false,true))
851  {
852  wxMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."),_("Warning"),wxOK | wxICON_INFORMATION, this);
853  return;
854  }
857 };
858 
#define DEBUG_INFO(msg)
Definition: utils.h:69
implementation of huginApp Class
void SetEmptyImage()
set preview to empty image
LensCalImageCtrl * m_preview
Definition: LensCalFrame.h:109
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
const unsigned int cps_per_line
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
image previewer for lens calibration GUI
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
#define DEBUG_TRACE(msg)
Definition: utils.h:67
The main window frame.
Definition: LensCalFrame.h:56
double m_focallength
Definition: LensCalFrame.h:114
HuginBase::SrcPanoImage * GetPanoImage()
return the SrcPanoImage from the given filename
Somewhere to specify what variables belong to what.
wxChoice * m_choice_projection
Definition: LensCalFrame.h:107
void OnSelectPreviewContent(wxCommandEvent &e)
some helper classes for graphes
wxString doubleTowxString(double d, int digits)
Definition: wxPlatform.cpp:31
END_EVENT_TABLE()
include file for the hugin project
simple popup to show graph
Definition: GraphTools.h:38
void OnSaveLens(wxCommandEvent &e)
declaration of LensCal main frame class
void SaveLensToIni()
Lines findLines(vigra::BImage &edge, double length_threshold, double focal_length, double crop_factor)
find straightish non-crossing lines find straightish non-crossing lines in an edge map using 8-neighb...
Definition: FindLines.cpp:115
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition: Panorama.cpp:297
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program
Definition: LensDB.cpp:2010
void ShowFilenameWarning(wxWindow *parent, const wxArrayString filelist)
shows a dialog about filename with invalid characters, all names in filelist will be show in list ...
Definition: platform.cpp:515
simple class that forward the drop to the mainframe
Definition: LensCalFrame.h:41
virtual ~LensCalFrame()
destructor
class to access Hugins camera and lens database
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
file drag and drop handler method
void OnRefresh(wxCommandEvent &e)
Model for a panorama.
Definition: Panorama.h:152
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
Definition: Panorama.cpp:381
#define HUGIN_IMGCACHE_UPPERBOUND
void Optimize()
do the optimization
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
size_t GetSelectedValue(wxControlWithItems *list)
Returns the client value of the selected item from list.
Definition: LensTools.cpp:102
void OnShowLines(wxCommandEvent &e)
void OnShowDistortionGraph(wxCommandEvent &e)
show distortion graph
unsigned int m_resize_dimension
Definition: LensCalFrame.h:118
void SaveLensParameters(const wxString filename, HuginBase::Panorama *pano, unsigned int imgNr)
save the lens parameters of the image to a lens file named filename
Definition: LensTools.cpp:143
void setVar(const std::string &name, double val)
HuginBase::CPVector GetControlPoints(const SingleLine &line, const unsigned int imgNr, const unsigned int lineNr, const unsigned int numberOfCtrlPoints)
returns a HuginBase::CPVector with cps_per_lines
Definition: FindLines.cpp:141
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
void updateProgressDisplay()
called when a progress message should be displayed
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: LensCalApp.cpp:212
void OnAddImage(wxCommandEvent &e)
void OnImageSelected(wxCommandEvent &e)
#define DEFAULT_RESIZE_DIMENSION
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
Definition: SrcPanoImage.h:55
void EnableButtons()
enable all buttons and menu items depending on number of active images
void UpdateListString(unsigned int index)
double getVar(const std::string &name) const
HuginBase::SrcPanoImage::Projection m_projection
Definition: LensCalFrame.h:113
wxGraphTools::GraphPopupWindow * m_popup
Definition: LensCalFrame.h:131
void OnReset(wxCommandEvent &e)
vigra::BImage * detectEdges(const vigra::UInt8RGBImage &input, const double scale, const double threshold, const unsigned int resize_dimension, double &size_factor)
detect and mark edges in an edge image using Canny&#39;s algorithm
Definition: FindLines.cpp:76
!! from PTOptimise.h 1951
dialogs for loading and saving information from/to lens database
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition: Panorama.cpp:319
void OnOptimize(wxCommandEvent &e)
Same as above, but use a non const panorama.
bool ReadInputs(bool readFocalLength, bool readOptions, bool readLensParameter)
reads all input values into internal values
void OnFindLines(wxCommandEvent &e)
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
const wxString & GetXRCPath()
get the path to the xrc directory
void SelectListValue(wxControlWithItems *list, size_t newValue)
Selects the given value (stored in the client data) in the given list item.
Definition: LensTools.cpp:89
#define DEFAULT_LENSCAL_THRESHOLD
const LensCalPreviewMode GetMode()
return actual preview mode
std::vector< SingleLine > Lines
vector of extracted lines from image
Definition: LinesTypes.h:50
void OnExit(wxCommandEvent &e)
double m_edge_scale
Definition: LensCalFrame.h:116
wxListBox * m_images_list
Definition: LensCalFrame.h:108
bool containsInvalidCharacters(const wxString stringToTest)
returns true, if the given strings contains invalid characters
Definition: platform.cpp:502
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
void SetImage(ImageLineList *newList, unsigned int newIndex)
set preview setting to given ImageLineList
wxBitmap GetDistortionGraph(const HuginBase::SrcPanoImage &srcImage)
return wxBitmap with graph of distortion for given SrcPanoImage
Definition: GraphTools.cpp:193
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
static double calcHFOV(SrcPanoImage::Projection proj, double fl, double crop, vigra::Size2D imageSize)
calculate hfov of an image given focal length, image size and crop factor
platform/compiler specific stuff.
declaration of application class for lens calibrate application
#define DEFAULT_LENSCAL_SCALE
std::vector< ImageLineList * > m_images
list of all detected lines
Definition: LensCalFrame.h:111
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
std::vector< std::set< std::string > > OptimizeVector
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
const wxString GetFilename()
returns the filename
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
#define DEFAULT_MINLINELENGTH
HuginBase::Panorama GetPanorama()
return panorama object with all images
double m_minlinelength
Definition: LensCalFrame.h:119
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
void SetLens(const HuginBase::SrcPanoImage::Projection newProjection, const double newFocallength, const double newCropfactor)
updates the internal values of the lens (needed only for remapped image)
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
wxString GetFileDialogImageFilters()
return filter for image files, needed by file open dialog it contains all image format vigra can read...
Definition: platform.cpp:69
Panorama image options.
void switchParts(unsigned int ImageNr, unsigned int partNr)
switch a given image to a different part number.
void FillLensProjectionList(wxControlWithItems *list)
Fills a wxControlWithItem with all input projection formats, the client data contains the associated ...
Definition: LensTools.cpp:35
void SetMode(const LensCalPreviewMode newMode)
set which image (original, edge, remapped/corrected) should be drawn
void ParametersToDisplay()
set all parameter input wxTextField to internal values
void SetLensDistortions(const double newA, const double newB, const double newC, const double newD, const double newE)
updates the internal values of the lens distortions parameters (needed only for remapped image) ...
void OnRemoveImage(wxCommandEvent &e)
double m_edge_threshold
Definition: LensCalFrame.h:117
void UpdateList(bool restoreSelection)
updates the list box with current values
void SetShowLines(bool showLines)
void OnSaveProject(wxCommandEvent &e)
double m_cropfactor
Definition: LensCalFrame.h:115
void AddImages(wxArrayString files)