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 "base_wx/wxutils.h"
36 #include "huginapp/ImageCache.h"
37 #include "LensCalFrame.h"
38 #include <wx/app.h>
39 #include "LensCalApp.h"
40 #include "hugin/config_defaults.h"
42 #include "lensdb/LensDB.h"
43 #include "base_wx/wxLensDB.h"
45 
46 const unsigned int cps_per_line=10;
47 
48 #define DEFAULT_LENSCAL_SCALE 2.0
49 #define DEFAULT_LENSCAL_THRESHOLD 4.0
50 #define DEFAULT_RESIZE_DIMENSION 1600
51 #define DEFAULT_MINLINELENGTH 0.3
52 
54 bool FileDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
55 {
56  DEBUG_TRACE("OnDropFiles");
57  LensCalFrame* frame=wxGetApp().GetLensCalFrame();
58  if (!frame)
59  return false;
60 
61  // try to add as images
62  wxArrayString files;
63  wxArrayString invalidFiles;
64  for (unsigned int i=0; i< filenames.GetCount(); i++)
65  {
66  wxFileName file(filenames[i]);
67  if (file.GetExt().CmpNoCase("jpg") == 0 ||
68  file.GetExt().CmpNoCase("jpeg") == 0 ||
69  file.GetExt().CmpNoCase("tif") == 0 ||
70  file.GetExt().CmpNoCase("tiff") == 0 ||
71  file.GetExt().CmpNoCase("png") == 0 ||
72  file.GetExt().CmpNoCase("bmp") == 0 ||
73  file.GetExt().CmpNoCase("gif") == 0 ||
74  file.GetExt().CmpNoCase("pnm") == 0 ||
75  file.GetExt().CmpNoCase("sun") == 0 ||
76  file.GetExt().CmpNoCase("hdr") == 0 ||
77  file.GetExt().CmpNoCase("viff") == 0 )
78  {
79  if(containsInvalidCharacters(file.GetFullPath()))
80  {
81  invalidFiles.push_back(file.GetFullPath());
82  }
83  else
84  {
85  files.push_back(file.GetFullPath());
86  };
87  }
88  }
89  if(!invalidFiles.empty())
90  {
91  ShowFilenameWarning(frame, invalidFiles);
92  }
93  // we got some images to add.
94  if (!files.empty())
95  {
96  // use a Command to ensure proper undo and updating of GUI parts
97  frame->AddImages(files);
98  }
99  return true;
100 }
101 
102 LensCalFrame::LensCalFrame(wxWindow* parent)
103 {
104  DEBUG_TRACE("");
105  // load our children. some children might need special
106  // initialization. this will be done later.
107  wxXmlResource::Get()->LoadFrame(this, parent, "lenscal_frame");
108  DEBUG_TRACE("");
109 
110  // load our menu bar
111 #ifdef __WXMAC__
112  wxApp::s_macExitMenuItemId = XRCID("menu_quit");
113 #endif
114  SetMenuBar(wxXmlResource::Get()->LoadMenuBar(this, "lenscal_menubar"));
115 
116  m_choice_projection=XRCCTRL(*this,"lenscal_proj_choice",wxChoice);
118  m_images_list=XRCCTRL(*this,"lenscal_images_list",wxListBox);
119  m_images_list->Bind(wxEVT_LISTBOX, &LensCalFrame::OnImageSelected, this);
120  m_preview=XRCCTRL(*this,"lenscal_preview",LensCalImageCtrl);
121 
122  wxConfigBase* config = wxConfigBase::Get();
123  config->Read("/LensCalFrame/EdgeScale",&m_edge_scale,DEFAULT_LENSCAL_SCALE);
124  config->Read("/LensCalFrame/EdgeThreshold",&m_edge_threshold,DEFAULT_LENSCAL_THRESHOLD);
125  m_resize_dimension=config->Read("/LensCalFrame/ResizeDimension",DEFAULT_RESIZE_DIMENSION);
126  config->Read("/LensCalFrame/MinLineLength",&m_minlinelength,DEFAULT_MINLINELENGTH);
128 
129  bool selected;
130  config->Read("/LensCalFrame/Optimize_a",&selected,false);
131  XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->SetValue(selected);
132  config->Read("/LensCalFrame/Optimize_b",&selected,true);
133  XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->SetValue(selected);
134  config->Read("/LensCalFrame/Optimize_c",&selected,false);
135  XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->SetValue(selected);
136  config->Read("/LensCalFrame/Optimize_de",&selected,false);
137  XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->SetValue(selected);
138 
139  // set the minimize icon
140 #ifdef __WXMSW__
141  wxIconBundle myIcons(GetXRCPath() + "data/hugin.ico", wxBITMAP_TYPE_ICO);
142  SetIcons(myIcons);
143 #else
144  wxIcon myIcon(GetXRCPath() + "data/hugin.png",wxBITMAP_TYPE_PNG);
145  SetIcon(myIcon);
146 #endif
147  SetTitle(_("Hugin Lens calibration GUI"));
148 
149  // create a new drop handler. wxwindows deletes the automatically
150  SetDropTarget(new FileDropTarget());
151 
152  // create a status bar
153  const int fields (2);
154  CreateStatusBar(fields);
155  int widths[fields] = {-1, 85};
156  SetStatusWidths( fields, &widths[0]);
157 
158  // Set sizing characteristics
159  //set minumum size
160 #if defined __WXMAC__ || defined __WXMSW__
161  // a minimum nice looking size; smaller than this would clutter the layout.
162  SetSizeHints(900, 675);
163 #else
164  // For ASUS eeePc
165  SetSizeHints(780, 455); //set minumum size
166 #endif
167 
168  // set progress display for image cache.
169  ImageCache::getInstance().setProgressDisplay(this);
170 #if defined __WXMSW__
171  unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
172  unsigned long mem_low = config->Read("/ImageCache/UpperBound", HUGIN_IMGCACHE_UPPERBOUND);
173  unsigned long mem_high = config->Read("/ImageCache/UpperBoundHigh", (long) 0);
174  if (mem_high > 0) {
175  mem = ((unsigned long long) mem_high << 32) + mem_low;
176  }
177  else {
178  mem = mem_low;
179  }
180  ImageCache::getInstance().SetUpperLimit(mem);
181 #else
182  ImageCache::getInstance().SetUpperLimit(config->Read("/ImageCache/UpperBound", HUGIN_IMGCACHE_UPPERBOUND));
183 #endif
184  // bind event handler
185  Bind(wxEVT_MENU, &LensCalFrame::OnSaveProject, this, XRCID("menu_save"));
186  Bind(wxEVT_MENU, &LensCalFrame::OnExit, this, XRCID("menu_quit"));
187  Bind(wxEVT_BUTTON, &LensCalFrame::OnAddImage, this, XRCID("lenscal_add_image"));
188  Bind(wxEVT_BUTTON, &LensCalFrame::OnRemoveImage, this, XRCID("lenscal_remove_image"));
189  Bind(wxEVT_BUTTON, &LensCalFrame::OnFindLines, this, XRCID("lenscal_find_lines"));
190  Bind(wxEVT_BUTTON, &LensCalFrame::OnReset, this, XRCID("lenscal_reset"));
191  Bind(wxEVT_BUTTON, &LensCalFrame::OnOptimize, this, XRCID("lenscal_opt"));
192  Bind(wxEVT_BUTTON, &LensCalFrame::OnShowDistortionGraph, this, XRCID("lenscal_show_distortion_graph"));
193  Bind(wxEVT_BUTTON, &LensCalFrame::OnSaveLens, this, XRCID("lenscal_save_lens"));
194  Bind(wxEVT_BUTTON, &LensCalFrame::OnRefresh, this, XRCID("lenscal_refresh"));
195  Bind(wxEVT_CHOICE, &LensCalFrame::OnSelectPreviewContent, this, XRCID("lenscal_preview_content"));
196  Bind(wxEVT_CHECKBOX, &LensCalFrame::OnShowLines, this, XRCID("lenscal_show_lines"));
197  //disable buttons
198  EnableButtons();
199  XRCCTRL(*this, "lenscal_remove_image", wxButton)->Enable(false);
200 }
201 
203 {
204  DEBUG_TRACE("dtor");
206  ImageCache::getInstance().setProgressDisplay(0);
207  delete & ImageCache::getInstance();
208  // get the global config object
209  wxConfigBase* config = wxConfigBase::Get();
210  if(ReadInputs(false,true,false))
211  {
212  config->Write("/LensCalFrame/EdgeScale",m_edge_scale);
213  config->Write("/LensCalFrame/EdgeThreshold",m_edge_threshold);
214  config->Write("/LensCalFrame/ResizeDimension",(int)m_resize_dimension);
215  config->Write("/LensCalFrame/MinLineLength",m_minlinelength);
216  };
217  config->Write("/LensCalFrame/Optimize_a",XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue());
218  config->Write("/LensCalFrame/Optimize_b",XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue());
219  config->Write("/LensCalFrame/Optimize_c",XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue());
220  config->Write("/LensCalFrame/Optimize_de",XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue());
221  hugin_utils::StoreFramePosition(this, "LensCalFrame");
222  config->Flush();
223  //cleanup
224  for(unsigned int i=0;i<m_images.size();i++)
225  {
226  delete m_images[i];
227  };
228  m_images.clear();
230  DEBUG_TRACE("dtor end");
231 }
232 
234 {
235  XRCCTRL(*this,"lenscal_scale",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_scale,2));
236  XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_threshold, 2));
237  XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->SetValue(wxString::Format("%d", m_resize_dimension));
238  XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_minlinelength, 2));
239 };
240 
241 const wxString & LensCalFrame::GetXRCPath()
242 {
243  return wxGetApp().GetXRCPath();
244 };
245 
248 {
249  wxString msg;
250  if (!m_message.empty())
251  {
252  msg = wxGetTranslation(wxString(m_message.c_str(), wxConvLocal));
253  if (!m_filename.empty())
254  {
255  msg.Append(" ");
256  msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
257  };
258  };
259  GetStatusBar()->SetStatusText(msg, 0);
260 
261 #ifdef __WXMSW__
262  UpdateWindow(NULL);
263 #endif
264 }
265 
266 void LensCalFrame::OnExit(wxCommandEvent &e)
267 {
268  Close();
269 };
270 
271 void LensCalFrame::AddImages(wxArrayString files)
272 {
273  wxArrayString wrongSize;
274  wxArrayString wrongExif;
275  for (unsigned int i=0; i<files.GetCount(); i++)
276  {
277  ImageLineList* image=new ImageLineList(files[i]);
278  //check input
279  {
280  // check for black/white images
281  const HuginBase::FileMetaData metadata = image->GetPanoImage()->getFileMetadata();
282  HuginBase::FileMetaData::const_iterator it = metadata.find("pixeltype");
283  if (it != metadata.end())
284  {
285  if (it->second == "BILEVEL")
286  {
287  hugin_utils::HuginMessageBox(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()),
288  _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
289  delete image;
290  continue;
291  };
292  };
293  };
294  if(!m_images.empty())
295  {
296  const HuginBase::SrcPanoImage* image0=m_images[0]->GetPanoImage();
297  const HuginBase::SrcPanoImage* image1=image->GetPanoImage();
298  if(image0->getSize()!=image1->getSize())
299  {
300  wrongSize.push_back(files[i]);
301  delete image;
302  continue;
303  };
304  if(!image0->getExifMake().empty() && !image1->getExifMake().empty() &&
305  !image0->getExifModel().empty() && !image1->getExifModel().empty() &&
306  image0->getExifFocalLength()>0 && image1->getExifFocalLength()>0 &&
307  image0->getCropFactor()>0 && image1->getCropFactor()>0
308  )
309  {
310  if(image0->getExifMake()!=image1->getExifMake() ||
311  image0->getExifModel()!=image1->getExifModel() ||
312  image0->getExifFocalLength()!=image1->getExifFocalLength() ||
313  image0->getCropFactor()!=image1->getCropFactor())
314  {
315  //only show a warning, but continue processing
316  wrongExif.push_back(files[i]);
317  };
318  };
319  };
320  m_images.push_back(image);
321  SetStatusText(wxString::Format(_("Added %s"),image->GetFilename().c_str()));
322  if (image->GetPanoImage()->getExifFocalLength() > 0)
323  {
324  XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->SetValue(
325  hugin_utils::doubleTowxString(image->GetPanoImage()->getExifFocalLength(), 2)
326  );
327  };
328  if (image->GetPanoImage()->getExifCropFactor() > 0)
329  {
330  XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->SetValue(
331  hugin_utils::doubleTowxString(image->GetPanoImage()->getCropFactor(), 2)
332  );
333  };
334  SelectListValue(m_choice_projection,image->GetPanoImage()->getProjection());
335  }
336  UpdateList(false);
337  m_images_list->SetSelection(m_images_list->GetCount()-1);
338  wxCommandEvent e;
339  OnImageSelected(e);
340  EnableButtons();
341  if(!wrongSize.empty())
342  {
343  wxString fileText;
344  for(unsigned int i=0;i<wrongSize.size();i++)
345  {
346  wxFileName filename(wrongSize[i]);
347  fileText.Append(filename.GetFullName());
348  if(i<wrongSize.size()-1)
349  fileText.Append(", ");
350  };
351  hugin_utils::HuginMessageBox(wxString::Format(_("The size of the images (%s) does not match the already added image(s)."), fileText.c_str()),
352  _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
353  };
354  if(!wrongExif.empty())
355  {
356  wxString fileText;
357  for(unsigned int i=0;i<wrongExif.size();i++)
358  {
359  wxFileName filename(wrongExif[i]);
360  fileText.Append(filename.GetFullName());
361  if(i<wrongExif.size()-1)
362  fileText.Append(", ");
363  };
364  hugin_utils::HuginMessageBox(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()),
365  _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
366  };
367 };
368 
369 void LensCalFrame::OnAddImage(wxCommandEvent &e)
370 {
371  wxConfigBase* config = wxConfigBase::Get();
372  wxString path = config->Read("/actualPath", wxEmptyString);
373  wxFileDialog dlg(this,_("Add images"),
374  path, wxEmptyString,
376  wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST | wxFD_PREVIEW, wxDefaultPosition);
377  dlg.SetDirectory(path);
378 
379  // remember the image extension
380  wxString img_ext;
381  if (config->HasEntry("lastImageType")){
382  img_ext = config->Read("lastImageType").c_str();
383  }
384  if (img_ext == "all images")
385  dlg.SetFilterIndex(0);
386  else if (img_ext == "jpg")
387  dlg.SetFilterIndex(1);
388  else if (img_ext == "tiff")
389  dlg.SetFilterIndex(2);
390  else if (img_ext == "png")
391  dlg.SetFilterIndex(3);
392  else if (img_ext == "hdr")
393  dlg.SetFilterIndex(4);
394  else if (img_ext == "exr")
395  dlg.SetFilterIndex(5);
396  else if (img_ext == "all files")
397  dlg.SetFilterIndex(6);
398  DEBUG_INFO ( "Image extention: " << img_ext.mb_str(wxConvLocal) )
399 
400  // call the file dialog
401  if (dlg.ShowModal() == wxID_OK)
402  {
403  // get the selections
404  wxArrayString Pathnames;
405  dlg.GetPaths(Pathnames);
406 
407  // save the current path to config
408 #ifdef __WXGTK__
409  //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
410  config->Write("/actualPath", wxPathOnly(Pathnames[0]));
411 #else
412  config->Write("/actualPath", dlg.GetDirectory());
413 #endif
414 
415  wxArrayString invalidFiles;
416  for(unsigned int i=0;i<Pathnames.GetCount(); i++)
417  {
418  if(containsInvalidCharacters(Pathnames[i]))
419  {
420  invalidFiles.push_back(Pathnames[i]);
421  };
422  };
423  if(!invalidFiles.empty())
424  {
425  ShowFilenameWarning(this, invalidFiles);
426  }
427  else
428  {
429  AddImages(Pathnames);
430  };
431  DEBUG_INFO ( wxString::Format("img_ext: %d", dlg.GetFilterIndex()).mb_str(wxConvLocal) )
432  // save the image extension
433  switch ( dlg.GetFilterIndex() )
434  {
435  case 0: config->Write("lastImageType", "all images"); break;
436  case 1: config->Write("lastImageType", "jpg"); break;
437  case 2: config->Write("lastImageType", "tiff"); break;
438  case 3: config->Write("lastImageType", "png"); break;
439  case 4: config->Write("lastImageType", "hdr"); break;
440  case 5: config->Write("lastImageType", "exr"); break;
441  case 6: config->Write("lastImageType", "all files"); break;
442  }
443  }
444  else
445  {
446  // nothing to open
447  SetStatusText( _("Add Image: cancel"));
448  }
449  EnableButtons();
450 };
451 
452 void LensCalFrame::UpdateListString(unsigned int index)
453 {
454  wxFileName file(m_images[index]->GetFilename());
455  m_images_list->SetString(index,wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[index]->GetNrOfValidLines()));
456 };
457 
458 void LensCalFrame::UpdateList(bool restoreSelection)
459 {
460  int oldSelection=m_images_list->GetSelection();
461  m_images_list->Clear();
462  for(unsigned int i=0;i<m_images.size();i++)
463  {
464  wxFileName file(m_images[i]->GetFilename());
465  wxString text=wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[i]->GetNrOfValidLines());
466  m_images_list->Append(text);
467  };
468  if(oldSelection!=wxNOT_FOUND && restoreSelection)
469  {
470  m_images_list->SetSelection(oldSelection);
471  };
472  wxCommandEvent e;
473  OnImageSelected(e);
474 };
475 
476 void LensCalFrame::OnRemoveImage(wxCommandEvent &e)
477 {
478  int selection=m_images_list->GetSelection();
479  if(selection!=wxNOT_FOUND)
480  {
481  // remove file from cache
482  const std::string filename(m_images[selection]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
483  ImageCache::getInstance().removeImage(filename);
484  delete m_images[selection];
485  m_images.erase(m_images.begin()+selection);
486  UpdateList(false);
487  }
488  else
489  {
490  wxBell();
491  };
492  EnableButtons();
493 };
494 
496 {
497  const bool enabling = !m_images.empty();
498  XRCCTRL(*this,"lenscal_find_lines",wxButton)->Enable(enabling);
499  XRCCTRL(*this,"lenscal_opt",wxButton)->Enable(enabling);
500  XRCCTRL(*this, "lenscal_show_distortion_graph", wxButton)->Enable(enabling);
501  XRCCTRL(*this,"lenscal_save_lens",wxButton)->Enable(enabling);
502  GetMenuBar()->Enable(XRCID("menu_save"),enabling);
503 };
504 
505 bool LensCalFrame::ReadInputs(bool readFocalLength,bool readOptions,bool readLensParameter)
506 {
507  if(readFocalLength)
508  {
510  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->GetValue(), m_focallength))
511  return false;
512  if(m_focallength<1)
513  return false;
514  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->GetValue(), m_cropfactor))
515  return false;
516  if(m_cropfactor<0.1)
517  return false;
518  }
519  if(readOptions)
520  {
521  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_scale", wxTextCtrl)->GetValue(), m_edge_scale))
522  return false;
523  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->GetValue(), m_edge_threshold))
524  return false;
525  double resize_dim;
526  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->GetValue(), resize_dim))
527  return false;
528  if(resize_dim<100)
529  return false;
530  m_resize_dimension=(unsigned int)resize_dim;
531  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->GetValue(), m_minlinelength))
532  return false;
533  if(m_minlinelength<=0 || m_minlinelength>1)
534  return false;
535  };
536  if(readLensParameter)
537  {
538  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_a", wxTextCtrl)->GetValue(), m_a))
539  return false;
540  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_b", wxTextCtrl)->GetValue(), m_b))
541  return false;
542  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_c", wxTextCtrl)->GetValue(), m_c))
543  return false;
544  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_d", wxTextCtrl)->GetValue(), m_d))
545  return false;
546  if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_e", wxTextCtrl)->GetValue(), m_e))
547  return false;
548  }
549  return true;
550 };
551 
552 void LensCalFrame::OnFindLines(wxCommandEvent &e)
553 {
554  if(!ReadInputs(true,true,false))
555  {
556  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
557  return;
558  }
560  for(unsigned int i=0;i<m_images.size();i++)
561  {
562  std::string filename(m_images[i]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
563  ImageCache::EntryPtr img=ImageCache::getInstance().getImage(filename);
564  double scale;
565  SetStatusText(_("Detecting edges..."));
566  m_images[i]->SetEdgeImage(HuginLines::detectEdges(*(img->get8BitImage()),m_edge_scale,m_edge_threshold,m_resize_dimension,scale));
567  SetStatusText(_("Finding lines..."));
569  m_images[i]->ScaleLines(scale);
570  };
571  SetStatusText(_("Finished"));
572  UpdateList(true);
573 };
574 
575 void LensCalFrame::OnOptimize(wxCommandEvent &e)
576 {
577  if(!ReadInputs(true,false,true))
578  {
579  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
580  return;
581  }
582  unsigned int count=0;
583  for(unsigned int i=0;i<m_images.size();i++)
584  count+=m_images[i]->GetNrOfValidLines();
585  if(count==0)
586  {
587  hugin_utils::HuginMessageBox(_("There are no detected lines.\nPlease run \"Find lines\" first. If there are no lines found, change the parameters."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
588  return;
589  };
590  Optimize();
591 };
592 
593 void LensCalFrame::OnShowDistortionGraph(wxCommandEvent &e)
594 {
595  if (m_images.empty())
596  {
597  return;
598  };
599  if (!ReadInputs(true, false, true))
600  {
601  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
602  return;
603  };
604  delete m_popup;
605  HuginBase::SrcPanoImage image(*(m_images[0]->GetPanoImage()));
606  image.setProjection(m_projection);
607  image.setExifFocalLength(m_focallength);
608  image.setCropFactor(m_cropfactor);
609  image.setVar("a", m_a);
610  image.setVar("b", m_b);
611  image.setVar("c", m_c);
612  image.setVar("d", m_d);
613  image.setVar("e", m_e);
614  image.setHFOV(HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize()));
615 
617  wxWindow *button = (wxWindow*)e.GetEventObject();
618  wxPoint pos = button->ClientToScreen(wxPoint(0, 0));
619  m_popup->Position(pos, button->GetSize());
620  m_popup->Popup();
621 };
622 
624 {
625  HuginBase::Panorama pano;
627  unsigned int line_number=3;
628  for(unsigned int i=0;i<m_images.size();i++)
629  {
630  HuginBase::SrcPanoImage image(*(m_images[i]->GetPanoImage()));
631  image.setProjection(m_projection);
632  image.setExifFocalLength(m_focallength);
633  image.setCropFactor(m_cropfactor);
634  image.setVar("a",m_a);
635  image.setVar("b",m_b);
636  image.setVar("c",m_c);
637  image.setVar("d",m_d);
638  image.setVar("e",m_e);
639  double hfov = HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize());
640  image.setHFOV(hfov);
641  pano.addImage(image);
642  std::set<std::string> imgopt;
643  if(i==0)
644  {
645  if(XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue())
646  imgopt.insert("a");
647  if(XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue())
648  imgopt.insert("b");
649  if(XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue())
650  imgopt.insert("c");
651  if(XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue())
652  {
653  imgopt.insert("d");
654  imgopt.insert("e");
655  }
656  };
657  optvec.push_back(imgopt);
658  //now generate control points from lines
659  HuginLines::Lines lines=m_images[i]->GetLines();
660  for(unsigned j=0;j<lines.size();j++)
661  {
662  if(lines[j].status==HuginLines::valid_line)
663  {
664  HuginBase::CPVector cpv=GetControlPoints(lines[j],i,line_number,cps_per_line);
665  for(unsigned int k=0;k<cpv.size();k++)
666  pano.addCtrlPoint(cpv[k]);
667  line_number++;
668  };
669  };
670  };
671  //assign all images the same lens number
672  HuginBase::StandardImageVariableGroups variable_groups(pano);
673  HuginBase::ImageVariableGroup & lenses = variable_groups.getLenses();
674  if(pano.getNrOfImages()>1)
675  {
676  for(unsigned int i=1;i<pano.getNrOfImages();i++)
677  {
678  HuginBase::SrcPanoImage img = pano.getSrcImage(i);
679  lenses.switchParts(i,lenses.getPartNumber(0));
680  img.setExposureValue(0);
681  img.setWhiteBalanceRed(1);
682  img.setWhiteBalanceBlue(1);
683  pano.setSrcImage(i, img);
684  };
685  };
686  //set default exposure value
688  opts.outputExposureValue = 0;
690  pano.setOptions(opts);
691 
692  pano.setOptimizeVector(optvec);
693  return pano;
694 };
695 
697 {
698  SetStatusText(_("Optimizing lens distortion parameters..."));
701 
702  const HuginBase::SrcPanoImage img = pano.getImage(0);
703  m_a=img.getVar("a");
704  m_b=img.getVar("b");
705  m_c=img.getVar("c");
706  m_d=img.getVar("d");
707  m_e=img.getVar("e");
708  XRCCTRL(*this,"lenscal_a",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_a,5));
709  XRCCTRL(*this,"lenscal_b",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_b,5));
710  XRCCTRL(*this,"lenscal_c",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_c,5));
711  XRCCTRL(*this,"lenscal_d",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_d,3));
712  XRCCTRL(*this,"lenscal_e",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_e,3));
714  SetStatusText(_("Finished"));
715 };
716 
718 {
719  wxFileDialog dlg(this,
720  _("Save lens parameters file"),
721  wxConfigBase::Get()->Read("/lensPath",wxEmptyString), wxEmptyString,
722  _("Lens Project Files (*.ini)|*.ini|All files (*)|*"),
723  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
724  dlg.SetDirectory(wxConfigBase::Get()->Read("/lensPath",wxEmptyString));
725  if (dlg.ShowModal() == wxID_OK)
726  {
727  wxFileName filename(dlg.GetPath());
728  if(!filename.HasExt())
729  filename.SetExt("ini");
730  wxConfig::Get()->Write("/lensPath", dlg.GetDirectory()); // remember for later
731  if (filename.FileExists())
732  {
733  if (!hugin_utils::AskUserOverwrite(filename.GetFullPath(), _("Calibrate_lens_GUI"), this))
734  {
735  return;
736  }
737  }
739  SaveLensParameters(filename.GetFullPath(),&pano,0);
740  }
741 };
742 
743 void LensCalFrame::OnSaveLens(wxCommandEvent &e)
744 {
745  if(!ReadInputs(true,false,true))
746  {
747  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
748  return;
749  }
750  unsigned int count=0;
751  for(unsigned int i=0;i<m_images.size();i++)
752  count+=m_images[i]->GetNrOfValidLines();
753  if(count==0)
754  {
755  hugin_utils::HuginMessageBox(_("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."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
756  return;
757  };
758 
759  wxArrayString choices;
760  choices.push_back(_("Save lens parameters to ini file"));
761  choices.push_back(_("Save lens parameters to lens database"));
762  wxSingleChoiceDialog save_dlg(this,_("Saving lens data"),_("Save lens"),choices);
763  if(save_dlg.ShowModal()==wxID_OK)
764  {
765  if(save_dlg.GetSelection()==0)
766  {
767  SaveLensToIni();
768  }
769  else
770  {
772  SaveLensParameters(this,pano.getImage(0),false);
773  };
774  };
775 };
776 
777 void LensCalFrame::OnSaveProject(wxCommandEvent &e)
778 {
779  if(!ReadInputs(true,false,true))
780  {
781  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
782  return;
783  }
784 
785  wxFileDialog dlg(this,_("Save project file"),wxEmptyString,wxEmptyString,
786  _("Project files (*.pto)|*.pto|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
787  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
788  if (dlg.ShowModal() == wxID_OK)
789  {
790  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
791  wxFileName filename(dlg.GetPath());
792  if(!filename.HasExt())
793  filename.SetExt("pto");
794  if (filename.FileExists())
795  {
796  if (!hugin_utils::AskUserOverwrite(filename.GetFullPath(), _("Calibrate_lens_GUI"), this))
797  {
798  return;
799  }
800  }
802  const std::string output(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
803  pano.WritePTOFile(output, hugin_utils::getPathPrefix(output));
804  };
805 };
806 
807 void LensCalFrame::OnImageSelected(wxCommandEvent &e)
808 {
809  bool selected=m_images_list->GetSelection()!=wxNOT_FOUND;
810  XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(selected);
811  if(selected)
812  {
813  m_preview->SetImage(m_images[m_images_list->GetSelection()],m_images_list->GetSelection());
814  }
815  else
816  {
818  };
819 };
820 
822 {
824  XRCCTRL(*this,"lenscal_refresh",wxButton)->Enable(m_preview->GetMode()==LensCalImageCtrl::mode_corrected);
825 };
826 
827 void LensCalFrame::OnShowLines(wxCommandEvent &e)
828 {
829  m_preview->SetShowLines(XRCCTRL(*this,"lenscal_show_lines",wxCheckBox)->GetValue());
830  m_preview->Refresh(true);
831 };
832 
833 void LensCalFrame::OnReset(wxCommandEvent &e)
834 {
840 };
841 
842 void LensCalFrame::OnRefresh(wxCommandEvent &e)
843 {
844  if(!ReadInputs(true,false,true))
845  {
846  hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
847  return;
848  }
851 };
852 
#define DEBUG_INFO(msg)
Definition: utils.h:69
implementation of huginApp Class
bool AskUserOverwrite(const wxString &filename, const wxString &caption, wxWindow *parent)
ask user if the given file should be overwritten, return true if the user confirmed the overwritting ...
Definition: wxutils.cpp:233
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
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:523
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
LensCalFrame(wxWindow *parent)
constructor
size_t GetSelectedValue(wxControlWithItems *list)
Returns the client value of the selected item from list.
Definition: LensTools.cpp:103
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:144
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 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.
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Definition: wxutils.cpp:135
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:90
#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:510
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:192
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:36
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) ...
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
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)
double m_cropfactor
Definition: LensCalFrame.h:115
void OnSaveProject(wxCommandEvent &e)
void AddImages(wxArrayString files)