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
171 // bind event handler
172 Bind(wxEVT_MENU, &LensCalFrame::OnSaveProject, this, XRCID("menu_save"));
173 Bind(wxEVT_MENU, &LensCalFrame::OnExit, this, XRCID("menu_quit"));
174 Bind(wxEVT_BUTTON, &LensCalFrame::OnAddImage, this, XRCID("lenscal_add_image"));
175 Bind(wxEVT_BUTTON, &LensCalFrame::OnRemoveImage, this, XRCID("lenscal_remove_image"));
176 Bind(wxEVT_BUTTON, &LensCalFrame::OnFindLines, this, XRCID("lenscal_find_lines"));
177 Bind(wxEVT_BUTTON, &LensCalFrame::OnReset, this, XRCID("lenscal_reset"));
178 Bind(wxEVT_BUTTON, &LensCalFrame::OnOptimize, this, XRCID("lenscal_opt"));
179 Bind(wxEVT_BUTTON, &LensCalFrame::OnShowDistortionGraph, this, XRCID("lenscal_show_distortion_graph"));
180 Bind(wxEVT_BUTTON, &LensCalFrame::OnSaveLens, this, XRCID("lenscal_save_lens"));
181 Bind(wxEVT_BUTTON, &LensCalFrame::OnRefresh, this, XRCID("lenscal_refresh"));
182 Bind(wxEVT_CHOICE, &LensCalFrame::OnSelectPreviewContent, this, XRCID("lenscal_preview_content"));
183 Bind(wxEVT_CHECKBOX, &LensCalFrame::OnShowLines, this, XRCID("lenscal_show_lines"));
184 //disable buttons
186 XRCCTRL(*this, "lenscal_remove_image", wxButton)->Enable(false);
187}
188
190{
191 DEBUG_TRACE("dtor");
193 ImageCache::getInstance().setProgressDisplay(0);
194 delete & ImageCache::getInstance();
195 // get the global config object
196 wxConfigBase* config = wxConfigBase::Get();
197 if(ReadInputs(false,true,false))
198 {
199 config->Write("/LensCalFrame/EdgeScale",m_edge_scale);
200 config->Write("/LensCalFrame/EdgeThreshold",m_edge_threshold);
201 config->Write("/LensCalFrame/ResizeDimension",(int)m_resize_dimension);
202 config->Write("/LensCalFrame/MinLineLength",m_minlinelength);
203 };
204 config->Write("/LensCalFrame/Optimize_a",XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue());
205 config->Write("/LensCalFrame/Optimize_b",XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue());
206 config->Write("/LensCalFrame/Optimize_c",XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue());
207 config->Write("/LensCalFrame/Optimize_de",XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue());
208 hugin_utils::StoreFramePosition(this, "LensCalFrame");
209 config->Flush();
210 //cleanup
211 for(unsigned int i=0;i<m_images.size();i++)
212 {
213 delete m_images[i];
214 };
215 m_images.clear();
217 DEBUG_TRACE("dtor end");
218}
219
221{
222 XRCCTRL(*this,"lenscal_scale",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_scale,2));
223 XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_edge_threshold, 2));
224 XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->SetValue(wxString::Format("%d", m_resize_dimension));
225 XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_minlinelength, 2));
226};
227
229{
230 return wxGetApp().GetXRCPath();
231};
232
235{
237 if (!m_message.empty())
238 {
240 if (!m_filename.empty())
241 {
242 msg.Append(" ");
243 msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
244 };
245 };
246 GetStatusBar()->SetStatusText(msg, 0);
247
248#ifdef __WXMSW__
250#endif
251}
252
253void LensCalFrame::OnExit(wxCommandEvent &e)
254{
255 Close();
256};
257
259{
262 for (unsigned int i=0; i<files.GetCount(); i++)
263 {
264 ImageLineList* image=new ImageLineList(files[i]);
265 //check input
266 {
267 // check for black/white images
268 const HuginBase::FileMetaData metadata = image->GetPanoImage()->getFileMetadata();
269 HuginBase::FileMetaData::const_iterator it = metadata.find("pixeltype");
270 if (it != metadata.end())
271 {
272 if (it->second == "BILEVEL")
273 {
274 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()),
275 _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
276 delete image;
277 continue;
278 };
279 };
280 };
281 if(!m_images.empty())
282 {
283 const HuginBase::SrcPanoImage* image0=m_images[0]->GetPanoImage();
284 const HuginBase::SrcPanoImage* image1=image->GetPanoImage();
285 if(image0->getSize()!=image1->getSize())
286 {
287 wrongSize.push_back(files[i]);
288 delete image;
289 continue;
290 };
291 if(!image0->getExifMake().empty() && !image1->getExifMake().empty() &&
292 !image0->getExifModel().empty() && !image1->getExifModel().empty() &&
293 image0->getExifFocalLength()>0 && image1->getExifFocalLength()>0 &&
294 image0->getCropFactor()>0 && image1->getCropFactor()>0
295 )
296 {
297 if(image0->getExifMake()!=image1->getExifMake() ||
298 image0->getExifModel()!=image1->getExifModel() ||
299 image0->getExifFocalLength()!=image1->getExifFocalLength() ||
300 image0->getCropFactor()!=image1->getCropFactor())
301 {
302 //only show a warning, but continue processing
303 wrongExif.push_back(files[i]);
304 };
305 };
306 };
307 m_images.push_back(image);
308 SetStatusText(wxString::Format(_("Added %s"),image->GetFilename().c_str()));
309 if (image->GetPanoImage()->getExifFocalLength() > 0)
310 {
311 XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->SetValue(
312 hugin_utils::doubleTowxString(image->GetPanoImage()->getExifFocalLength(), 2)
313 );
314 };
315 if (image->GetPanoImage()->getExifCropFactor() > 0)
316 {
317 XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->SetValue(
318 hugin_utils::doubleTowxString(image->GetPanoImage()->getCropFactor(), 2)
319 );
320 };
321 SelectListValue(m_choice_projection,image->GetPanoImage()->getProjection());
322 }
323 UpdateList(false);
324 m_images_list->SetSelection(m_images_list->GetCount()-1);
325 wxCommandEvent e;
328 if(!wrongSize.empty())
329 {
331 for(unsigned int i=0;i<wrongSize.size();i++)
332 {
333 wxFileName filename(wrongSize[i]);
334 fileText.Append(filename.GetFullName());
335 if(i<wrongSize.size()-1)
336 fileText.Append(", ");
337 };
338 hugin_utils::HuginMessageBox(wxString::Format(_("The size of the images (%s) does not match the already added image(s)."), fileText.c_str()),
339 _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
340 };
341 if(!wrongExif.empty())
342 {
344 for(unsigned int i=0;i<wrongExif.size();i++)
345 {
346 wxFileName filename(wrongExif[i]);
347 fileText.Append(filename.GetFullName());
348 if(i<wrongExif.size()-1)
349 fileText.Append(", ");
350 };
351 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()),
352 _("Calibrate_lens_GUI"), wxOK | wxICON_EXCLAMATION, this);
353 };
354};
355
356void LensCalFrame::OnAddImage(wxCommandEvent &e)
357{
358 wxConfigBase* config = wxConfigBase::Get();
359 wxString path = config->Read("/actualPath", wxEmptyString);
360 wxFileDialog dlg(this,_("Add images"),
361 path, wxEmptyString,
364 dlg.SetDirectory(path);
365
366 // remember the image extension
368 if (config->HasEntry("lastImageType")){
369 img_ext = config->Read("lastImageType").c_str();
370 }
371 if (img_ext == "all images")
372 dlg.SetFilterIndex(0);
373 else if (img_ext == "jpg")
374 dlg.SetFilterIndex(1);
375 else if (img_ext == "tiff")
376 dlg.SetFilterIndex(2);
377 else if (img_ext == "png")
378 dlg.SetFilterIndex(3);
379 else if (img_ext == "hdr")
380 dlg.SetFilterIndex(4);
381 else if (img_ext == "exr")
382 dlg.SetFilterIndex(5);
383 else if (img_ext == "all files")
384 dlg.SetFilterIndex(6);
385 DEBUG_INFO ( "Image extention: " << img_ext.mb_str(wxConvLocal) )
386
387 // call the file dialog
388 if (dlg.ShowModal() == wxID_OK)
389 {
390 // get the selections
392 dlg.GetPaths(Pathnames);
393
394 // save the current path to config
395#ifdef __WXGTK__
396 //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
397 config->Write("/actualPath", wxPathOnly(Pathnames[0]));
398#else
399 config->Write("/actualPath", dlg.GetDirectory());
400#endif
401
403 for(unsigned int i=0;i<Pathnames.GetCount(); i++)
404 {
406 {
407 invalidFiles.push_back(Pathnames[i]);
408 };
409 };
410 if(!invalidFiles.empty())
411 {
413 }
414 else
415 {
417 };
418 DEBUG_INFO ( wxString::Format("img_ext: %d", dlg.GetFilterIndex()).mb_str(wxConvLocal) )
419 // save the image extension
420 switch ( dlg.GetFilterIndex() )
421 {
422 case 0: config->Write("lastImageType", "all images"); break;
423 case 1: config->Write("lastImageType", "jpg"); break;
424 case 2: config->Write("lastImageType", "tiff"); break;
425 case 3: config->Write("lastImageType", "png"); break;
426 case 4: config->Write("lastImageType", "hdr"); break;
427 case 5: config->Write("lastImageType", "exr"); break;
428 case 6: config->Write("lastImageType", "all files"); break;
429 }
430 }
431 else
432 {
433 // nothing to open
434 SetStatusText( _("Add Image: cancel"));
435 }
437};
438
439void LensCalFrame::UpdateListString(unsigned int index)
440{
441 wxFileName file(m_images[index]->GetFilename());
442 m_images_list->SetString(index,wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[index]->GetNrOfValidLines()));
443};
444
446{
447 int oldSelection=m_images_list->GetSelection();
448 m_images_list->Clear();
449 for(unsigned int i=0;i<m_images.size();i++)
450 {
451 wxFileName file(m_images[i]->GetFilename());
452 wxString text=wxString::Format(_("%s (%d lines)"),file.GetFullName().c_str(),m_images[i]->GetNrOfValidLines());
453 m_images_list->Append(text);
454 };
456 {
457 m_images_list->SetSelection(oldSelection);
458 };
459 wxCommandEvent e;
461};
462
463void LensCalFrame::OnRemoveImage(wxCommandEvent &e)
464{
465 int selection=m_images_list->GetSelection();
466 if(selection!=wxNOT_FOUND)
467 {
468 // remove file from cache
469 const std::string filename(m_images[selection]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
470 ImageCache::getInstance().removeImage(filename);
471 delete m_images[selection];
472 m_images.erase(m_images.begin()+selection);
473 UpdateList(false);
474 }
475 else
476 {
477 wxBell();
478 };
480};
481
483{
484 const bool enabling = !m_images.empty();
485 XRCCTRL(*this,"lenscal_find_lines",wxButton)->Enable(enabling);
486 XRCCTRL(*this,"lenscal_opt",wxButton)->Enable(enabling);
487 XRCCTRL(*this, "lenscal_show_distortion_graph", wxButton)->Enable(enabling);
488 XRCCTRL(*this,"lenscal_save_lens",wxButton)->Enable(enabling);
489 GetMenuBar()->Enable(XRCID("menu_save"),enabling);
490};
491
493{
495 {
497 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_focallength", wxTextCtrl)->GetValue(), m_focallength))
498 return false;
499 if(m_focallength<1)
500 return false;
501 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_cropfactor", wxTextCtrl)->GetValue(), m_cropfactor))
502 return false;
503 if(m_cropfactor<0.1)
504 return false;
505 }
506 if(readOptions)
507 {
508 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_scale", wxTextCtrl)->GetValue(), m_edge_scale))
509 return false;
510 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_threshold", wxTextCtrl)->GetValue(), m_edge_threshold))
511 return false;
512 double resize_dim;
513 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_resizedim", wxTextCtrl)->GetValue(), resize_dim))
514 return false;
515 if(resize_dim<100)
516 return false;
518 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_minlinelength", wxTextCtrl)->GetValue(), m_minlinelength))
519 return false;
521 return false;
522 };
524 {
525 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_a", wxTextCtrl)->GetValue(), m_a))
526 return false;
527 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_b", wxTextCtrl)->GetValue(), m_b))
528 return false;
529 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_c", wxTextCtrl)->GetValue(), m_c))
530 return false;
531 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_d", wxTextCtrl)->GetValue(), m_d))
532 return false;
533 if (!hugin_utils::str2double(XRCCTRL(*this, "lenscal_e", wxTextCtrl)->GetValue(), m_e))
534 return false;
535 }
536 return true;
537};
538
539void LensCalFrame::OnFindLines(wxCommandEvent &e)
540{
541 if(!ReadInputs(true,true,false))
542 {
543 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
544 return;
545 }
547 for(unsigned int i=0;i<m_images.size();i++)
548 {
549 std::string filename(m_images[i]->GetFilename().mb_str(HUGIN_CONV_FILENAME));
550 ImageCache::EntryPtr img=ImageCache::getInstance().getImage(filename);
551 double scale;
552 SetStatusText(_("Detecting edges..."));
553 m_images[i]->SetEdgeImage(HuginLines::detectEdges(*(img->get8BitImage()),m_edge_scale,m_edge_threshold,m_resize_dimension,scale));
554 SetStatusText(_("Finding lines..."));
556 m_images[i]->ScaleLines(scale);
557 };
558 SetStatusText(_("Finished"));
559 UpdateList(true);
560};
561
562void LensCalFrame::OnOptimize(wxCommandEvent &e)
563{
564 if(!ReadInputs(true,false,true))
565 {
566 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
567 return;
568 }
569 unsigned int count=0;
570 for(unsigned int i=0;i<m_images.size();i++)
571 count+=m_images[i]->GetNrOfValidLines();
572 if(count==0)
573 {
574 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);
575 return;
576 };
577 Optimize();
578};
579
581{
582 if (m_images.empty())
583 {
584 return;
585 };
586 if (!ReadInputs(true, false, true))
587 {
588 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
589 return;
590 };
591 delete m_popup;
592 HuginBase::SrcPanoImage image(*(m_images[0]->GetPanoImage()));
593 image.setProjection(m_projection);
594 image.setExifFocalLength(m_focallength);
595 image.setCropFactor(m_cropfactor);
596 image.setVar("a", m_a);
597 image.setVar("b", m_b);
598 image.setVar("c", m_c);
599 image.setVar("d", m_d);
600 image.setVar("e", m_e);
601 image.setHFOV(HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize()));
602
604 wxWindow *button = (wxWindow*)e.GetEventObject();
605 wxPoint pos = button->ClientToScreen(wxPoint(0, 0));
606 m_popup->Position(pos, button->GetSize());
607 m_popup->Popup();
608};
609
611{
614 unsigned int line_number=3;
615 for(unsigned int i=0;i<m_images.size();i++)
616 {
617 HuginBase::SrcPanoImage image(*(m_images[i]->GetPanoImage()));
618 image.setProjection(m_projection);
619 image.setExifFocalLength(m_focallength);
620 image.setCropFactor(m_cropfactor);
621 image.setVar("a",m_a);
622 image.setVar("b",m_b);
623 image.setVar("c",m_c);
624 image.setVar("d",m_d);
625 image.setVar("e",m_e);
626 double hfov = HuginBase::SrcPanoImage::calcHFOV(image.getProjection(), image.getExifFocalLength(), image.getCropFactor(), image.getSize());
627 image.setHFOV(hfov);
628 pano.addImage(image);
629 std::set<std::string> imgopt;
630 if(i==0)
631 {
632 if(XRCCTRL(*this,"lenscal_opt_a",wxCheckBox)->GetValue())
633 imgopt.insert("a");
634 if(XRCCTRL(*this,"lenscal_opt_b",wxCheckBox)->GetValue())
635 imgopt.insert("b");
636 if(XRCCTRL(*this,"lenscal_opt_c",wxCheckBox)->GetValue())
637 imgopt.insert("c");
638 if(XRCCTRL(*this,"lenscal_opt_de",wxCheckBox)->GetValue())
639 {
640 imgopt.insert("d");
641 imgopt.insert("e");
642 }
643 };
644 optvec.push_back(imgopt);
645 //now generate control points from lines
646 HuginLines::Lines lines=m_images[i]->GetLines();
647 for(unsigned j=0;j<lines.size();j++)
648 {
649 if(lines[j].status==HuginLines::valid_line)
650 {
652 for(unsigned int k=0;k<cpv.size();k++)
653 pano.addCtrlPoint(cpv[k]);
654 line_number++;
655 };
656 };
657 };
658 //assign all images the same lens number
661 if(pano.getNrOfImages()>1)
662 {
663 for(unsigned int i=1;i<pano.getNrOfImages();i++)
664 {
666 lenses.switchParts(i,lenses.getPartNumber(0));
667 img.setExposureValue(0);
668 img.setWhiteBalanceRed(1);
669 img.setWhiteBalanceBlue(1);
670 pano.setSrcImage(i, img);
671 };
672 };
673 //set default exposure value
675 opts.outputExposureValue = 0;
677 pano.setOptions(opts);
678
679 pano.setOptimizeVector(optvec);
680 return pano;
681};
682
684{
685 SetStatusText(_("Optimizing lens distortion parameters..."));
688
689 const HuginBase::SrcPanoImage img = pano.getImage(0);
690 m_a=img.getVar("a");
691 m_b=img.getVar("b");
692 m_c=img.getVar("c");
693 m_d=img.getVar("d");
694 m_e=img.getVar("e");
695 XRCCTRL(*this,"lenscal_a",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_a,5));
696 XRCCTRL(*this,"lenscal_b",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_b,5));
697 XRCCTRL(*this,"lenscal_c",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_c,5));
698 XRCCTRL(*this,"lenscal_d",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_d,3));
699 XRCCTRL(*this,"lenscal_e",wxTextCtrl)->SetValue(hugin_utils::doubleTowxString(m_e,3));
701 SetStatusText(_("Finished"));
702};
703
705{
706 wxFileDialog dlg(this,
707 _("Save lens parameters file"),
708 wxConfigBase::Get()->Read("/lensPath",wxEmptyString), wxEmptyString,
709 _("Lens Project Files (*.ini)|*.ini|All files (*)|*"),
711 dlg.SetDirectory(wxConfigBase::Get()->Read("/lensPath",wxEmptyString));
712 if (dlg.ShowModal() == wxID_OK)
713 {
714 wxFileName filename(dlg.GetPath());
715 if(!filename.HasExt())
716 filename.SetExt("ini");
717 wxConfig::Get()->Write("/lensPath", dlg.GetDirectory()); // remember for later
718 if (filename.FileExists())
719 {
720 if (!hugin_utils::AskUserOverwrite(filename.GetFullPath(), _("Calibrate_lens_GUI"), this))
721 {
722 return;
723 }
724 }
726 SaveLensParameters(filename.GetFullPath(),&pano,0);
727 }
728};
729
730void LensCalFrame::OnSaveLens(wxCommandEvent &e)
731{
732 if(!ReadInputs(true,false,true))
733 {
734 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
735 return;
736 }
737 unsigned int count=0;
738 for(unsigned int i=0;i<m_images.size();i++)
739 count+=m_images[i]->GetNrOfValidLines();
740 if(count==0)
741 {
742 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);
743 return;
744 };
745
747 choices.push_back(_("Save lens parameters to ini file"));
748 choices.push_back(_("Save lens parameters to lens database"));
749 wxSingleChoiceDialog save_dlg(this,_("Saving lens data"),_("Save lens"),choices);
750 if(save_dlg.ShowModal()==wxID_OK)
751 {
752 if(save_dlg.GetSelection()==0)
753 {
755 }
756 else
757 {
759 SaveLensParameters(this,pano.getImage(0),false);
760 };
761 };
762};
763
764void LensCalFrame::OnSaveProject(wxCommandEvent &e)
765{
766 if(!ReadInputs(true,false,true))
767 {
768 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
769 return;
770 }
771
772 wxFileDialog dlg(this,_("Save project file"),wxEmptyString,wxEmptyString,
773 _("Project files (*.pto)|*.pto|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
774 dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
775 if (dlg.ShowModal() == wxID_OK)
776 {
777 wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
778 wxFileName filename(dlg.GetPath());
779 if(!filename.HasExt())
780 filename.SetExt("pto");
781 if (filename.FileExists())
782 {
783 if (!hugin_utils::AskUserOverwrite(filename.GetFullPath(), _("Calibrate_lens_GUI"), this))
784 {
785 return;
786 }
787 }
789 const std::string output(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
791 };
792};
793
794void LensCalFrame::OnImageSelected(wxCommandEvent &e)
795{
796 bool selected=m_images_list->GetSelection()!=wxNOT_FOUND;
797 XRCCTRL(*this,"lenscal_remove_image",wxButton)->Enable(selected);
798 if(selected)
799 {
800 m_preview->SetImage(m_images[m_images_list->GetSelection()],m_images_list->GetSelection());
801 }
802 else
803 {
805 };
806};
807
809{
811 XRCCTRL(*this,"lenscal_refresh",wxButton)->Enable(m_preview->GetMode()==LensCalImageCtrl::mode_corrected);
812};
813
814void LensCalFrame::OnShowLines(wxCommandEvent &e)
815{
816 m_preview->SetShowLines(XRCCTRL(*this,"lenscal_show_lines",wxCheckBox)->GetValue());
817 m_preview->Refresh(true);
818};
819
828
829void LensCalFrame::OnRefresh(wxCommandEvent &e)
830{
831 if(!ReadInputs(true,false,true))
832 {
833 hugin_utils::HuginMessageBox(_("There are invalid values in the input boxes.\nPlease check your inputs."), _("Calibrate_lens_GUI"), wxOK | wxICON_INFORMATION, this);
834 return;
835 }
838};
839
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:37
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.
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
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:198
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.