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