Hugin trunk 0.1
Loading...
Searching...
No Matches
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"
42#include "lensdb/LensDB.h"
43#include "base_wx/wxLensDB.h"
45
46const 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
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;
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 {
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
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);
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);
143#else
144 wxIcon myIcon(GetXRCPath() + "data/hugin.png",wxBITMAP_TYPE_PNG);
146#endif
147 SetTitle(_("Hugin Lens calibration GUI"));
148
149 // create a new drop handler. wxwindows deletes the automatically
151
152 // create a status bar
153 const int fields (2);
155 int widths[fields] = {-1, 85};
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
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
242{
243 return wxGetApp().GetXRCPath();
244};
245
248{
250 if (!m_message.empty())
251 {
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__
263#endif
264}
265
266void LensCalFrame::OnExit(wxCommandEvent &e)
267{
268 Close();
269};
270
272{
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;
341 if(!wrongSize.empty())
342 {
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 {
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
369void 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,
377 dlg.SetDirectory(path);
378
379 // remember the image extension
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
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
416 for(unsigned int i=0;i<Pathnames.GetCount(); i++)
417 {
419 {
420 invalidFiles.push_back(Pathnames[i]);
421 };
422 };
423 if(!invalidFiles.empty())
424 {
426 }
427 else
428 {
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 }
450};
451
452void 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
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 };
469 {
470 m_images_list->SetSelection(oldSelection);
471 };
472 wxCommandEvent e;
474};
475
476void 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 };
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
506{
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;
531 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->GetValue(), m_minlinelength))
532 return false;
534 return false;
535 };
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
552void 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
575void 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
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{
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 {
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
674 if(pano.getNrOfImages()>1)
675 {
676 for(unsigned int i=1;i<pano.getNrOfImages();i++)
677 {
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 (*)|*"),
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
743void 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
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 {
768 }
769 else
770 {
772 SaveLensParameters(this,pano.getImage(0),false);
773 };
774 };
775};
776
777void 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));
804 };
805};
806
807void 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
827void LensCalFrame::OnShowLines(wxCommandEvent &e)
828{
829 m_preview->SetShowLines(XRCCTRL(*this,"lenscal_show_lines",wxCheckBox)->GetValue());
830 m_preview->Refresh(true);
831};
832
841
842void 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
declaration of application class for lens calibrate application
#define DEFAULT_LENSCAL_SCALE
const unsigned int cps_per_line
#define DEFAULT_LENSCAL_THRESHOLD
#define DEFAULT_RESIZE_DIMENSION
#define DEFAULT_MINLINELENGTH
declaration of LensCal main frame class
class to access Hugins camera and lens database
void SaveLensParameters(const wxString filename, HuginBase::Panorama *pano, unsigned int imgNr)
save the lens parameters of the image to a lens file named filename
void FillLensProjectionList(wxControlWithItems *list)
Fills a wxControlWithItem with all input projection formats, the client data contains the associated ...
Definition LensTools.cpp:36
size_t GetSelectedValue(wxControlWithItems *list)
Returns the client value of the selected item from list.
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
some helper classes for graphes
!! from PTOptimise.h 1951
Somewhere to specify what variables belong to what.
simple class that forward the drop to the mainframe
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
file drag and drop handler method
Same as above, but use a non const panorama.
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program
Definition LensDB.cpp:2010
Panorama image options.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition Panorama.h:481
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition Panorama.cpp:297
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
Definition Panorama.cpp:381
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition Panorama.cpp:319
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
double getVar(const std::string &name) const
void setVar(const std::string &name, double val)
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
HuginBase::SrcPanoImage * GetPanoImage()
return the SrcPanoImage from the given filename
const wxString GetFilename()
returns the filename
The main window frame.
bool ReadInputs(bool readFocalLength, bool readOptions, bool readLensParameter)
reads all input values into internal values
HuginBase::SrcPanoImage::Projection m_projection
void UpdateList(bool restoreSelection)
updates the list box with current values
void ParametersToDisplay()
set all parameter input wxTextField to internal values
void AddImages(wxArrayString files)
const wxString & GetXRCPath()
get the path to the xrc directory
void OnReset(wxCommandEvent &e)
void OnExit(wxCommandEvent &e)
void OnFindLines(wxCommandEvent &e)
std::vector< ImageLineList * > m_images
list of all detected lines
void OnSaveProject(wxCommandEvent &e)
LensCalFrame(wxWindow *parent)
constructor
void OnShowDistortionGraph(wxCommandEvent &e)
show distortion graph
void Optimize()
do the optimization
double m_edge_scale
virtual ~LensCalFrame()
destructor
wxGraphTools::GraphPopupWindow * m_popup
wxChoice * m_choice_projection
void OnImageSelected(wxCommandEvent &e)
void updateProgressDisplay()
called when a progress message should be displayed
double m_minlinelength
void OnSelectPreviewContent(wxCommandEvent &e)
unsigned int m_resize_dimension
void OnShowLines(wxCommandEvent &e)
void OnAddImage(wxCommandEvent &e)
wxListBox * m_images_list
double m_cropfactor
void OnRefresh(wxCommandEvent &e)
void OnOptimize(wxCommandEvent &e)
void OnRemoveImage(wxCommandEvent &e)
void OnSaveLens(wxCommandEvent &e)
LensCalImageCtrl * m_preview
void UpdateListString(unsigned int index)
HuginBase::Panorama GetPanorama()
return panorama object with all images
double m_edge_threshold
double m_focallength
void EnableButtons()
enable all buttons and menu items depending on number of active images
image previewer for lens calibration GUI
void SetShowLines(bool showLines)
void SetMode(const LensCalPreviewMode newMode)
set which image (original, edge, remapped/corrected) should be drawn
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 SetLens(const HuginBase::SrcPanoImage::Projection newProjection, const double newFocallength, const double newCropfactor)
updates the internal values of the lens (needed only for remapped image)
const LensCalPreviewMode GetMode()
return actual preview mode
void SetImage(ImageLineList *newList, unsigned int newIndex)
set preview setting to given ImageLineList
void SetEmptyImage()
set preview to empty image
simple popup to show graph
Definition GraphTools.h:39
#define HUGIN_IMGCACHE_UPPERBOUND
implementation of huginApp Class
#define HUGIN_CONV_FILENAME
Definition platform.h:40
#define DEBUG_TRACE(msg)
Definition utils.h:67
#define DEBUG_INFO(msg)
Definition utils.h:69
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
std::vector< ControlPoint > CPVector
std::vector< std::set< std::string > > OptimizeVector
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
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...
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's algorithm
Definition FindLines.cpp:76
std::vector< SingleLine > Lines
vector of extracted lines from image
Definition LinesTypes.h:50
bool str2double(const wxString &s, double &d)
wxString doubleTowxString(double d, int digits)
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
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition wxutils.cpp:176
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:106
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition utils.cpp:184
wxBitmap GetDistortionGraph(const HuginBase::SrcPanoImage &srcImage)
return wxBitmap with graph of distortion for given SrcPanoImage
include file for the hugin project
include file for the hugin project
wxString GetFileDialogImageFilters()
return filter for image files, needed by file open dialog it contains all image format vigra can read...
Definition platform.cpp:70
bool containsInvalidCharacters(const wxString stringToTest)
returns true, if the given strings contains invalid characters
Definition platform.cpp:511
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:524
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
dialogs for loading and saving information from/to lens database
platform/compiler specific stuff.