00001
00002
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <config.h>
00028 #include "panoinc_WX.h"
00029
00030 #include "panoinc.h"
00031
00032 #include "PT/PTOptimise.h"
00033
00034 #include "hugin/OptimizePanel.h"
00035 #include "hugin/CommandHistory.h"
00036 #include "hugin/MainFrame.h"
00037 #include "base_wx/MyProgressDialog.h"
00038 #include "base_wx/PTWXDlg.h"
00039 #include "hugin/config_defaults.h"
00040 #include "hugin/ImagesTree.h"
00041 #include "panodata/OptimizerSwitches.h"
00042 #include "hugin/PanoOperation.h"
00043
00044 using namespace std;
00045 using namespace PT;
00046 using namespace hugin_utils;
00047
00048
00049
00050
00051
00052 BEGIN_EVENT_TABLE(OptimizePanel, wxPanel)
00053 EVT_CLOSE(OptimizePanel::OnClose)
00054 EVT_BUTTON(XRCID("optimize_panel_optimize"), OptimizePanel::OnOptimizeButton)
00055 EVT_BUTTON(XRCID("optimize_panel_reset"), OptimizePanel::OnReset)
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
00068 if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
00069 return false;
00070 }
00071
00072
00073
00074
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
00086 m_images_tree_list = XRCCTRL(*this, "optimize_panel_images", ImagesTreeCtrl);
00087 DEBUG_ASSERT(m_images_tree_list);
00088 m_lens_tree_list = XRCCTRL(*this, "optimize_panel_lenses", ImagesTreeCtrl);
00089 DEBUG_ASSERT(m_lens_tree_list);
00090
00091 m_edit_cb = XRCCTRL(*this, "optimizer_panel_edit_script", wxCheckBox);
00092 DEBUG_ASSERT(m_edit_cb);
00093
00094 XRCCTRL(*this, "optimizer_panel_splitter", wxSplitterWindow)->SetSashGravity(0.66);
00095
00096 wxString text(_("Any variables below which are bold and underlined will be optimized."));
00097 text.Append(wxT(" "));
00098 #if defined __WXMAC__ || defined __WXOSX_COCOA__
00099 text.Append(_("Use command + left mouse click to toggle state of variables."));
00100 #else
00101 text.Append(_("Use control + left mouse click to toggle state of variables."));
00102 #endif
00103 text.Append(wxT(" "));
00104 text.Append(_("Variables which shown in normal font will act as references or anchors."));
00105 XRCCTRL(*this, "optimizer_panel_information_text", wxStaticText)->SetLabel(text);
00106
00107 return true;
00108 }
00109
00110 void OptimizePanel::Init(PT::Panorama * pano)
00111 {
00112 DEBUG_TRACE("");
00113 m_pano = pano;
00114
00115
00116 m_pano->addObserver(this);
00117 m_images_tree_list->Init(m_pano);
00118 m_images_tree_list->SetOptimizerMode();
00119 m_images_tree_list->SetDisplayMode(ImagesTreeCtrl::DISPLAY_POSITION);
00120
00121 m_lens_tree_list->Init(m_pano);
00122 m_lens_tree_list->SetOptimizerMode();
00123 m_lens_tree_list->SetGroupMode(ImagesTreeCtrl::GROUP_LENS);
00124 m_lens_tree_list->SetDisplayMode(ImagesTreeCtrl::DISPLAY_LENS);
00125 }
00126
00127 void OptimizePanel::SetGuiLevel(GuiLevel newGuiLevel)
00128 {
00129 m_images_tree_list->SetGuiLevel(newGuiLevel);
00130 m_lens_tree_list->SetGuiLevel(newGuiLevel);
00131 };
00132
00133 OptimizePanel::~OptimizePanel()
00134 {
00135 DEBUG_TRACE("dtor, writing config");
00136 wxConfigBase::Get()->Write(wxT("/OptimizePanel/OnlyActiveImages"),m_only_active_images_cb->IsChecked() ? 1l : 0l);
00137
00138 m_pano->removeObserver(this);
00139 DEBUG_TRACE("dtor end");
00140 }
00141
00142 void OptimizePanel::panoramaChanged(PT::Panorama & pano)
00143 {
00144
00145 m_images_tree_list->Enable(m_pano->getOptimizerSwitch()==0);
00146 m_lens_tree_list->Enable(m_pano->getOptimizerSwitch()==0);
00147 m_edit_cb->Enable(m_pano->getOptimizerSwitch()==0);
00148 }
00149
00150 void OptimizePanel::panoramaImagesChanged(PT::Panorama &pano,
00151 const PT::UIntSet & imgNr)
00152 {
00153 XRCCTRL(*this, "optimize_panel_optimize", wxButton)->Enable(pano.getNrOfImages()>0);
00154 XRCCTRL(*this, "optimize_panel_reset", wxButton)->Enable(pano.getNrOfImages()>0);
00155 };
00156
00157 void OptimizePanel::OnOptimizeButton(wxCommandEvent & e)
00158 {
00159 DEBUG_TRACE("");
00160
00161
00162 UIntSet imgs;
00163 if (m_only_active_images_cb->IsChecked() || m_pano->getOptimizerSwitch()!=0)
00164 {
00165
00166 imgs = m_pano->getActiveImages();
00167 if (imgs.size() == 0)
00168 {
00169 wxMessageBox(_("The project does not contain any active images.\nPlease activate at least one image in the (fast) preview window.\nOptimization canceled."),
00170 #ifdef _WINDOWS
00171 _("Hugin"),
00172 #else
00173 wxT(""),
00174 #endif
00175 wxICON_ERROR | wxOK);
00176 return;
00177 }
00178 }
00179 else
00180 {
00181 fill_set(imgs, 0, m_pano->getNrOfImages()-1);
00182 }
00183 runOptimizer(imgs);
00184 }
00185
00186 void OptimizePanel::runOptimizer(const UIntSet & imgs)
00187 {
00188 DEBUG_TRACE("");
00189
00190
00191 int mode=m_pano->getOptimizerSwitch();
00192
00193 Panorama optPano = m_pano->getSubset(imgs);
00194 PanoramaOptions opts = optPano.getOptions();
00195 switch(opts.getProjection())
00196 {
00197 case PanoramaOptions::RECTILINEAR:
00198 case PanoramaOptions::CYLINDRICAL:
00199 case PanoramaOptions::EQUIRECTANGULAR:
00200 break;
00201 default:
00202
00203 opts.setProjection(PanoramaOptions::EQUIRECTANGULAR);
00204 optPano.setOptions(opts);
00205 break;
00206 }
00207 UIntSet allImg;
00208 fill_set(allImg,0, imgs.size()-1);
00209
00210 char *p = setlocale(LC_ALL,NULL);
00211 char *oldlocale = strdup(p);
00212 setlocale(LC_ALL,"C");
00213
00214 if (mode & HuginBase::OPT_PAIR )
00215 {
00216
00217 CPVector cps = optPano.getCtrlPoints();
00218 CPVector newCP;
00219 for (CPVector::const_iterator it = cps.begin(); it != cps.end(); it++)
00220 {
00221 if (it->mode == ControlPoint::X_Y)
00222 {
00223 newCP.push_back(*it);
00224 }
00225 }
00226 optPano.setCtrlPoints(newCP);
00227
00228
00229 deregisterPTWXDlgFcn();
00230 {
00231 wxBusyCursor bc;
00232
00233 PTools::autoOptimise(optPano);
00234 }
00235 #ifdef DEBUG
00236
00237 DEBUG_DEBUG("panorama after autoOptimise():");
00238 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00239 #endif
00240
00241 registerPTWXDlgFcn(MainFrame::Get());
00242
00243 optPano.setCtrlPoints(cps);
00244 PTools::optimize(optPano);
00245 #ifdef DEBUG
00246
00247 DEBUG_DEBUG("panorama after optimise():");
00248 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00249 #endif
00250
00251 }
00252 else
00253 {
00254 if (m_edit_cb->IsChecked() && mode==0)
00255 {
00256
00257 ostringstream scriptbuf;
00258 optPano.printPanoramaScript(scriptbuf, optPano.getOptimizeVector(), optPano.getOptions(), allImg, true);
00259
00260 wxDialog * edit_dlg = wxXmlResource::Get()->LoadDialog(this, wxT("edit_script_dialog"));
00261 wxTextCtrl *txtCtrl=XRCCTRL(*edit_dlg,"script_edit_text",wxTextCtrl);
00262 txtCtrl->SetValue(wxString(scriptbuf.str().c_str(), *wxConvCurrent));
00263
00264 char * script = 0;
00265 if (edit_dlg->ShowModal() == wxID_OK)
00266 {
00267 script = strdup(txtCtrl->GetValue().mb_str(*wxConvCurrent));
00268 }
00269 else
00270 {
00271 return;
00272 }
00273 PTools::optimize(optPano, script);
00274 free(script);
00275 }
00276 else
00277 {
00278 PTools::optimize(optPano);
00279 }
00280 #ifdef DEBUG
00281
00282 DEBUG_DEBUG("panorama after optimise():");
00283 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
00284 #endif
00285 }
00286
00287 setlocale(LC_ALL,oldlocale);
00288 free(oldlocale);
00289 #ifdef __WXMSW__
00290
00291
00292
00293 wxTheApp->ProcessIdle();
00294 #endif
00295
00296 if (AskApplyResult(optPano))
00297 {
00298 GlobalCmdHist::getInstance().addCommand(
00299 new PT::UpdateVariablesCPSetCmd(*m_pano, imgs, optPano.getVariables(), optPano.getCtrlPoints())
00300 );
00301 }
00302 }
00303
00304 bool OptimizePanel::AskApplyResult(const Panorama & pano)
00305 {
00306 double min;
00307 double max;
00308 double mean;
00309 double var;
00310 pano.calcCtrlPntsErrorStats( min, max, mean, var);
00311
00312
00313 bool smallHFOV=false;
00314 bool highDist = false;
00315 const VariableMapVector & vars = pano.getVariables();
00316 for (VariableMapVector::const_iterator it = vars.begin() ; it != vars.end(); it++)
00317 {
00318 if (const_map_get(*it,"v").getValue() < 1.0) smallHFOV = true;
00319 if (fabs(const_map_get(*it,"a").getValue()) > 0.8) highDist = true;
00320 if (fabs(const_map_get(*it,"b").getValue()) > 0.8) highDist = true;
00321 if (fabs(const_map_get(*it,"c").getValue()) > 0.8) highDist = true;
00322 }
00323
00324 wxString msg;
00325 int style=0;
00326 if (smallHFOV)
00327 {
00328 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?"));
00329 style = wxYES_NO;
00330 }
00331 else
00332 {
00333 if (highDist)
00334 {
00335 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?"),
00336 mean, sqrt(var), max);
00337 style = wxYES_NO | wxICON_EXCLAMATION;
00338 }
00339 else
00340 {
00341 msg.Printf(_("Optimizer run finished.\nResults:\n average control point distance: %f\n standard deviation: %f\n maximum: %f\n\nApply the changes?"),
00342 mean, sqrt(var), max);
00343 style = wxYES_NO | wxICON_EXCLAMATION;
00344 }
00345 };
00346
00347 int id = wxMessageBox(msg,_("Optimization result"),style,this);
00348
00349 return id == wxYES;
00350 }
00351
00352 void OptimizePanel::OnClose(wxCloseEvent& event)
00353 {
00354 DEBUG_TRACE("OnClose");
00355
00356 if (event.CanVeto())
00357 {
00358 event.Veto();
00359 Hide();
00360 DEBUG_DEBUG("Hiding");
00361 }
00362 else
00363 {
00364 DEBUG_DEBUG("Closing");
00365 Destroy();
00366 }
00367 }
00368
00369 void OptimizePanel::OnReset(wxCommandEvent& e)
00370 {
00371 PanoOperation::ResetOperation op(PanoOperation::ResetOperation::RESET_DIALOG_LENS);
00372 PT::PanoCommand* cmd=op.GetCommand(this,*m_pano, m_images_tree_list->GetSelectedImages(), MainFrame::Get()->GetGuiLevel());
00373 if(cmd!=NULL)
00374 {
00375 GlobalCmdHist::getInstance().addCommand(cmd);
00376 };
00377
00378 };
00379
00380 IMPLEMENT_DYNAMIC_CLASS(OptimizePanel, wxPanel)
00381
00382
00383 OptimizePanelXmlHandler::OptimizePanelXmlHandler()
00384 : wxXmlResourceHandler()
00385 {
00386 AddWindowStyles();
00387 }
00388
00389 wxObject *OptimizePanelXmlHandler::DoCreateResource()
00390 {
00391 XRC_MAKE_INSTANCE(cp, OptimizePanel)
00392
00393 cp->Create(m_parentAsWindow,
00394 GetID(),
00395 GetPosition(), GetSize(),
00396 GetStyle(wxT("style")),
00397 GetName());
00398
00399 SetupWindow( cp);
00400
00401 return cp;
00402 }
00403
00404 bool OptimizePanelXmlHandler::CanHandle(wxXmlNode *node)
00405 {
00406 return IsOfClass(node, wxT("OptimizePanel"));
00407 }
00408
00409 IMPLEMENT_DYNAMIC_CLASS(OptimizePanelXmlHandler, wxXmlResourceHandler)