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

Generated on 13 Feb 2016 for Hugintrunk by  doxygen 1.4.7