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

Generated on 22 Feb 2017 for Hugintrunk by  doxygen 1.4.7