OptimizePanel.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /*  This program is free software; you can redistribute it and/or
00012  *  modify it under the terms of the GNU General Public
00013  *  License as published by the Free Software Foundation; either
00014  *  version 2 of the License, or (at your option) any later version.
00015  *
00016  *  This software is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *  General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public
00022  *  License along with this software. If not, see
00023  *  <http://www.gnu.org/licenses/>.
00024  *
00025  */
00026 
00027 #include <config.h>
00028 #include "panoinc_WX.h"
00029 
00030 #include "panoinc.h"
00031 
00032 #include <panotools/PanoToolsOptimizerWrapper.h>
00033 #include <algorithms/optimizer/PTOptimizer.h>
00034 #include <algorithms/basic/CalculateCPStatistics.h>
00035 
00036 #include "hugin/OptimizePanel.h"
00037 #include "base_wx/CommandHistory.h"
00038 #include "base_wx/PanoCommand.h"
00039 #include "hugin/MainFrame.h"
00040 #include "base_wx/PTWXDlg.h"
00041 #include "hugin/config_defaults.h"
00042 #include "hugin/ImagesTree.h"
00043 #include "panodata/OptimizerSwitches.h"
00044 #include "hugin/PanoOperation.h"
00045 #include "base_wx/LensTools.h"
00046 
00047 //============================================================================
00048 //============================================================================
00049 //============================================================================
00050 
00051 BEGIN_EVENT_TABLE(OptimizePanel, wxPanel)
00052     EVT_CLOSE(OptimizePanel::OnClose)
00053     EVT_BUTTON(XRCID("optimize_panel_optimize"), OptimizePanel::OnOptimizeButton)
00054     EVT_BUTTON(XRCID("optimize_panel_reset"), OptimizePanel::OnReset)
00055     EVT_CHECKBOX(XRCID("optimizer_panel_only_active_images"), OptimizePanel::OnCheckOnlyActiveImages)
00056 END_EVENT_TABLE()
00057 
00058 
00059 OptimizePanel::OptimizePanel()
00060 {
00061     DEBUG_TRACE("");
00062 }
00063 
00064 bool OptimizePanel::Create(wxWindow* parent, wxWindowID id , const wxPoint& pos, const wxSize& size, long style, const wxString& name)
00065 {
00066     DEBUG_TRACE("");
00067     // Not needed here, wxPanel::Create is called by LoadPanel below
00068     if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
00069         return false;
00070     }
00071 
00072     // create a sub-panel and load class into it!
00073 
00074     // wxPanel::Create is called in here!
00075     wxXmlResource::Get()->LoadPanel(this, wxT("optimize_panel"));
00076     wxPanel * panel = XRCCTRL(*this, "optimize_panel", wxPanel);
00077 
00078     wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
00079     topsizer->Add(panel, 1, wxEXPAND, 0);
00080     SetSizer( topsizer );
00081 
00082     m_only_active_images_cb = XRCCTRL(*this, "optimizer_panel_only_active_images", wxCheckBox);
00083     DEBUG_ASSERT(m_only_active_images_cb);
00084     m_only_active_images_cb->SetValue(wxConfigBase::Get()->Read(wxT("/OptimizePanel/OnlyActiveImages"),1l) != 0);
00085     MainFrame::Get()->SetOptimizeOnlyActiveImages(m_only_active_images_cb->GetValue());
00086 
00087     m_images_tree_list = XRCCTRL(*this, "optimize_panel_images", ImagesTreeCtrl);
00088     DEBUG_ASSERT(m_images_tree_list);
00089     m_lens_tree_list = XRCCTRL(*this, "optimize_panel_lenses", ImagesTreeCtrl);
00090     DEBUG_ASSERT(m_lens_tree_list);
00091 
00092     m_edit_cb = XRCCTRL(*this, "optimizer_panel_edit_script", wxCheckBox);
00093     DEBUG_ASSERT(m_edit_cb);
00094 
00095     XRCCTRL(*this, "optimizer_panel_splitter", wxSplitterWindow)->SetSashGravity(0.66);
00096 
00097     wxString text(_("Any variables below which are bold and underlined will be optimized."));
00098     text.Append(wxT(" "));
00099 #if defined __WXMAC__ || defined __WXOSX_COCOA__
00100     text.Append(_("Use command + left mouse click to toggle state of variables."));
00101 #else
00102     text.Append(_("Use control + left mouse click to toggle state of variables."));
00103 #endif
00104     text.Append(wxT(" "));
00105     text.Append(_("Variables which shown in normal font will act as references or anchors."));
00106     XRCCTRL(*this, "optimizer_panel_information_text", wxStaticText)->SetLabel(text);
00107 
00108     return true;
00109 }
00110 
00111 void OptimizePanel::Init(HuginBase::Panorama * pano)
00112 {
00113     DEBUG_TRACE("");
00114     m_pano = pano;
00115 
00116     // observe the panorama
00117     m_pano->addObserver(this);
00118     m_images_tree_list->Init(m_pano);
00119     m_images_tree_list->SetOptimizerMode();
00120     m_images_tree_list->SetDisplayMode(ImagesTreeCtrl::DISPLAY_POSITION);
00121 
00122     m_lens_tree_list->Init(m_pano);
00123     m_lens_tree_list->SetOptimizerMode();
00124     m_lens_tree_list->SetGroupMode(ImagesTreeCtrl::GROUP_LENS);
00125     m_lens_tree_list->SetDisplayMode(ImagesTreeCtrl::DISPLAY_LENS);
00126 }
00127 
00128 void OptimizePanel::SetGuiLevel(GuiLevel newGuiLevel)
00129 {
00130     m_images_tree_list->SetGuiLevel(newGuiLevel);
00131     m_lens_tree_list->SetGuiLevel(newGuiLevel);
00132 };
00133 
00134 OptimizePanel::~OptimizePanel()
00135 {
00136     DEBUG_TRACE("dtor, writing config");
00137     wxConfigBase::Get()->Write(wxT("/OptimizePanel/OnlyActiveImages"),m_only_active_images_cb->IsChecked() ? 1l : 0l);
00138 
00139     m_pano->removeObserver(this);
00140     DEBUG_TRACE("dtor end");
00141 }
00142 
00143 void OptimizePanel::panoramaChanged(HuginBase::Panorama & pano)
00144 {
00145     //Show(m_pano->getOptimizerSwitch()==0);
00146     m_images_tree_list->Enable(m_pano->getOptimizerSwitch()==0);
00147     m_lens_tree_list->Enable(m_pano->getOptimizerSwitch()==0);
00148     m_edit_cb->Enable(m_pano->getOptimizerSwitch()==0);
00149 }
00150 
00151 void OptimizePanel::panoramaImagesChanged(HuginBase::Panorama &pano,
00152                                           const HuginBase::UIntSet & imgNr)
00153 {
00154     XRCCTRL(*this, "optimize_panel_optimize", wxButton)->Enable(pano.getNrOfImages()>0);
00155     XRCCTRL(*this, "optimize_panel_reset", wxButton)->Enable(pano.getNrOfImages()>0);    
00156 };
00157 
00158 void OptimizePanel::OnOptimizeButton(wxCommandEvent & e)
00159 {
00160     DEBUG_TRACE("");
00161     // run optimizer
00162 
00163     HuginBase::UIntSet imgs;
00164     if (m_only_active_images_cb->IsChecked() || m_pano->getOptimizerSwitch()!=0)
00165     {
00166         // use only selected images.
00167         imgs = m_pano->getActiveImages();
00168         if (imgs.size() == 0)
00169         {
00170             wxMessageBox(_("The project does not contain any active images.\nPlease activate at least one image in the (fast) preview window.\nOptimization canceled."),
00171 #ifdef _WIN32
00172                 _("Hugin"),
00173 #else
00174                 wxT(""),
00175 #endif
00176                 wxICON_ERROR | wxOK);
00177             return;
00178         }
00179     }
00180     else
00181     {
00182         fill_set(imgs, 0, m_pano->getNrOfImages()-1);
00183     }
00184     if (CheckLensStacks(m_pano, true))
00185     {
00186         runOptimizer(imgs);
00187     };
00188 }
00189 
00190 void OptimizePanel::runOptimizer(const HuginBase::UIntSet & imgs)
00191 {
00192     DEBUG_TRACE("");
00193     // open window that shows a status dialog, and allows to
00194     // apply the results
00195     int mode=m_pano->getOptimizerSwitch();
00196     // remember active window for dialogs
00197     wxWindow* activeWindow = wxGetActiveWindow();
00198 
00199     HuginBase::Panorama optPano = m_pano->getSubset(imgs);
00200     HuginBase::PanoramaOptions opts = optPano.getOptions();
00201     switch(opts.getProjection())
00202     {
00203         case HuginBase::PanoramaOptions::RECTILINEAR:
00204         case HuginBase::PanoramaOptions::CYLINDRICAL:
00205         case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
00206             break;
00207         default:
00208             // temporarily change to equirectangular
00209             opts.setProjection(HuginBase::PanoramaOptions::EQUIRECTANGULAR);
00210             optPano.setOptions(opts);
00211             break;
00212     }
00213     HuginBase::UIntSet allImg;
00214     fill_set(allImg,0, imgs.size()-1);
00215 
00216     char *p = setlocale(LC_ALL,NULL);
00217     char *oldlocale = strdup(p);
00218     setlocale(LC_ALL,"C");
00219 
00220     if (mode & HuginBase::OPT_PAIR )
00221     {
00222         // temporarily disable PT progress dialog..
00223         deregisterPTWXDlgFcn();
00224         {
00225             wxBusyCursor bc;
00226             // run pairwise optimizer
00227             HuginBase::AutoOptimise(optPano).run();
00228         }
00229 #ifdef DEBUG
00230         // print optimized script to cout
00231         DEBUG_DEBUG("panorama after autoOptimise():");
00232         optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00233 #endif
00234 
00235         registerPTWXDlgFcn();
00236         // do global optimisation
00237         HuginBase::PTools::optimize(optPano);
00238 #ifdef DEBUG
00239         // print optimized script to cout
00240         DEBUG_DEBUG("panorama after optimise():");
00241         optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00242 #endif
00243 
00244     }
00245     else
00246     {
00247         if (m_edit_cb->IsChecked() && mode==0)
00248         {
00249             // show and edit script..
00250             std::ostringstream scriptbuf;
00251             optPano.printPanoramaScript(scriptbuf, optPano.getOptimizeVector(), optPano.getOptions(), allImg, true);
00252             // open a text dialog with an editor inside
00253             wxDialog * edit_dlg = wxXmlResource::Get()->LoadDialog(this, wxT("edit_script_dialog"));
00254             wxTextCtrl *txtCtrl=XRCCTRL(*edit_dlg,"script_edit_text",wxTextCtrl);
00255             txtCtrl->SetValue(wxString(scriptbuf.str().c_str(), *wxConvCurrent));
00256 
00257             char * script = 0;
00258             if (edit_dlg->ShowModal() == wxID_OK)
00259             {
00260                 script = strdup(txtCtrl->GetValue().mb_str(*wxConvCurrent));
00261             }
00262             else
00263             {
00264                 setlocale(LC_ALL,oldlocale);
00265                 free(oldlocale);
00266                 return;
00267             }
00268             HuginBase::PTools::optimize(optPano, script);
00269             free(script);
00270         }
00271         else
00272         {
00273             HuginBase::PTools::optimize(optPano);
00274         }
00275 #ifdef DEBUG
00276         // print optimized script to cout
00277         DEBUG_DEBUG("panorama after optimise():");
00278         optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00279 #endif
00280     }
00281 
00282     setlocale(LC_ALL,oldlocale);
00283     free(oldlocale);
00284 #ifdef __WXMSW__
00285     // the progress window of the optimizer is marked for deletion
00286     // but the final deletion happens only in the idle event
00287     // so we need to process the event to really close the progress window
00288     wxTheApp->ProcessIdle();
00289 #endif
00290     // calculate control point errors and display text.
00291     if (AskApplyResult(activeWindow, optPano))
00292     {
00293         PanoCommand::GlobalCmdHist::getInstance().addCommand(
00294             new PanoCommand::UpdateVariablesCPSetCmd(*m_pano, imgs, optPano.getVariables(), optPano.getCtrlPoints())
00295         );
00296     }
00297 }
00298 
00299 bool OptimizePanel::AskApplyResult(wxWindow* activeWindow, const HuginBase::Panorama & pano)
00300 {
00301     double min;
00302     double max;
00303     double mean;
00304     double var;
00305     HuginBase::CalculateCPStatisticsError::calcCtrlPntsErrorStats(pano, min, max, mean, var, -1, m_only_active_images_cb->IsChecked());
00306 
00307     // check for HFOV lines. if smaller than 1 report a warning;
00308     // also check for high distortion coefficients.
00309     bool smallHFOV=false;
00310     bool highDist = false;
00311     const HuginBase::VariableMapVector & vars = pano.getVariables();
00312     for (HuginBase::VariableMapVector::const_iterator it = vars.begin(); it != vars.end(); ++it)
00313     {
00314         if (const_map_get(*it,"v").getValue() < 1.0) smallHFOV = true;
00315         if (fabs(const_map_get(*it,"a").getValue()) > 0.8) highDist = true;
00316         if (fabs(const_map_get(*it,"b").getValue()) > 0.8) highDist = true;
00317         if (fabs(const_map_get(*it,"c").getValue()) > 0.8) highDist = true;
00318     }
00319 
00320     wxString msg;
00321     int style=0;
00322     if (smallHFOV)
00323     {
00324         msg.Printf( _("Optimizer run finished.\nWARNING: a very small Field of View (v) has been estimated\n\nThe results are probably invalid.\n\nOptimization of the Field of View (v) of partial panoramas can lead to bad results.\nTry adding more images and control points.\n\nApply the changes anyway?"));
00325         style = wxYES_NO;
00326     }
00327     else
00328     {
00329         if (highDist)
00330         {
00331             msg.Printf(_("Optimizer run finished.\nResults:\n average control point distance: %f\n standard deviation: %f\n maximum: %f\n\n*WARNING*: very high distortion coefficients (a,b,c) have been estimated.\nThe results are probably invalid.\nOnly optimize all distortion parameters when many, well spread control points are used.\nPlease reset the a,b and c parameters to zero and add more control points\n\nApply the changes anyway?"),
00332                    mean, sqrt(var), max);
00333             style = wxYES_NO | wxICON_EXCLAMATION;
00334         }
00335         else
00336         {
00337             msg.Printf(_("Optimizer run finished.\nResults:\n average control point distance: %f\n standard deviation: %f\n maximum: %f\n\nApply the changes?"),
00338                    mean, sqrt(var), max);
00339             style = wxYES_NO | wxICON_EXCLAMATION;
00340         }
00341     };
00342 
00343     int id = wxMessageBox(msg, _("Optimization result"), style, activeWindow);
00344 
00345     return id == wxYES;
00346 }
00347 
00348 void OptimizePanel::OnClose(wxCloseEvent& event)
00349 {
00350     DEBUG_TRACE("OnClose");
00351     // do not close, just hide if we're not forced
00352     if (event.CanVeto())
00353     {
00354         event.Veto();
00355         Hide();
00356         DEBUG_DEBUG("Hiding");
00357     }
00358     else
00359     {
00360         DEBUG_DEBUG("Closing");
00361         Destroy();
00362     }
00363 }
00364 
00365 void OptimizePanel::OnReset(wxCommandEvent& e)
00366 {
00367     PanoOperation::ResetOperation op(PanoOperation::ResetOperation::RESET_DIALOG_LENS);
00368     PanoCommand::PanoCommand* cmd=op.GetCommand(this,*m_pano, m_images_tree_list->GetSelectedImages(), MainFrame::Get()->GetGuiLevel());
00369     if(cmd!=NULL)
00370     {
00371         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
00372     };
00373 
00374 };
00375 
00376 void OptimizePanel::OnCheckOnlyActiveImages(wxCommandEvent &e)
00377 {
00378     MainFrame::Get()->SetOptimizeOnlyActiveImages(m_only_active_images_cb->IsChecked());
00379 };
00380 
00381 void OptimizePanel::SetOnlyActiveImages(const bool onlyActive)
00382 {
00383     m_only_active_images_cb->SetValue(onlyActive);
00384 };
00385 
00386 IMPLEMENT_DYNAMIC_CLASS(OptimizePanel, wxPanel)
00387 
00388 
00389 OptimizePanelXmlHandler::OptimizePanelXmlHandler()
00390                 : wxXmlResourceHandler()
00391 {
00392     AddWindowStyles();
00393 }
00394 
00395 wxObject *OptimizePanelXmlHandler::DoCreateResource()
00396 {
00397     XRC_MAKE_INSTANCE(cp, OptimizePanel)
00398 
00399     cp->Create(m_parentAsWindow,
00400                    GetID(),
00401                    GetPosition(), GetSize(),
00402                    GetStyle(wxT("style")),
00403                    GetName());
00404 
00405     SetupWindow( cp);
00406 
00407     return cp;
00408 }
00409 
00410 bool OptimizePanelXmlHandler::CanHandle(wxXmlNode *node)
00411 {
00412     return IsOfClass(node, wxT("OptimizePanel"));
00413 }
00414 
00415 IMPLEMENT_DYNAMIC_CLASS(OptimizePanelXmlHandler, wxXmlResourceHandler)

Generated on 28 Sep 2016 for Hugintrunk by  doxygen 1.4.7