Hugin trunk 0.1
Loading...
Searching...
No Matches
OptimizePanel.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
11/* This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this software. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 */
26
27#include "hugin_config.h"
28#include "panoinc_WX.h"
29
30#include "panoinc.h"
31
36
37#include "hugin/OptimizePanel.h"
39#include "base_wx/PanoCommand.h"
40#include "hugin/MainFrame.h"
41#include "base_wx/PTWXDlg.h"
43#include "hugin/ImagesTree.h"
45#include "hugin/PanoOperation.h"
46#include "base_wx/LensTools.h"
47#include "base_wx/wxutils.h"
48
49//============================================================================
50//============================================================================
51//============================================================================
52
57
58bool OptimizePanel::Create(wxWindow* parent, wxWindowID id , const wxPoint& pos, const wxSize& size, long style, const wxString& name)
59{
60 DEBUG_TRACE("");
61 // Not needed here, wxPanel::Create is called by LoadPanel below
62 if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
63 return false;
64 }
65
66 // create a sub-panel and load class into it!
67
68 // wxPanel::Create is called in here!
69 wxXmlResource::Get()->LoadPanel(this, "optimize_panel");
70 wxPanel * panel = XRCCTRL(*this, "optimize_panel", wxPanel);
71
73 topsizer->Add(panel, 1, wxEXPAND, 0);
75
76 m_only_active_images_cb = XRCCTRL(*this, "optimizer_panel_only_active_images", wxCheckBox);
78 m_only_active_images_cb->SetValue(false);
80 m_ignore_line_cp = XRCCTRL(*this, "optimizer_panel_ignore_line_cp", wxCheckBox);
82 m_ignore_line_cp->SetValue(false);
84
85 m_images_tree_list = XRCCTRL(*this, "optimize_panel_images", ImagesTreeCtrl);
87 m_lens_tree_list = XRCCTRL(*this, "optimize_panel_lenses", ImagesTreeCtrl);
89 SetOnlyActiveImages(wxConfigBase::Get()->Read("/OptimizePanel/OnlyActiveImages", 1l) != 0);
90
91 m_edit_cb = XRCCTRL(*this, "optimizer_panel_edit_script", wxCheckBox);
93
94 XRCCTRL(*this, "optimizer_panel_splitter", wxSplitterWindow)->SetSashGravity(0.66);
95 // bind other events
97 Bind(wxEVT_BUTTON, &OptimizePanel::OnOptimizeButton, this, XRCID("optimize_panel_optimize"));
98 Bind(wxEVT_BUTTON, &OptimizePanel::OnReset, this, XRCID("optimize_panel_reset"));
99
100 return true;
101}
102
119
125
127{
128 m_pano->removeObserver(this);
129 DEBUG_TRACE("dtor end");
130}
131
133{
134 //Show(m_pano->getOptimizerSwitch()==0);
137 m_edit_cb->Enable(m_pano->getOptimizerSwitch()==0);
138}
139
141 const HuginBase::UIntSet & imgNr)
142{
143 XRCCTRL(*this, "optimize_panel_optimize", wxButton)->Enable(pano.getNrOfImages()>0);
144 XRCCTRL(*this, "optimize_panel_reset", wxButton)->Enable(pano.getNrOfImages()>0);
145};
146
147void OptimizePanel::OnOptimizeButton(wxCommandEvent & e)
148{
149 DEBUG_TRACE("");
150 // run optimizer
152 if (m_only_active_images_cb->IsChecked() || m_pano->getOptimizerSwitch()!=0)
153 {
154 // use only selected images.
155 imgs = m_pano->getActiveImages();
156 if (imgs.empty())
157 {
158 hugin_utils::HuginMessageBox(_("The project does not contain any active images.\nPlease activate at least one image in the (fast) preview window.\nOptimization canceled."),
159 _("Hugin"), wxICON_ERROR | wxOK, wxGetActiveWindow());
160 return;
161 }
162 }
163 else
164 {
165 fill_set(imgs, 0, m_pano->getNrOfImages()-1);
166 }
167 if (CheckLensStacks(m_pano, true))
168 {
169 runOptimizer(imgs, m_ignore_line_cp->IsChecked());
170 };
171}
172
174{
175 DEBUG_TRACE("");
176 // open window that shows a status dialog, and allows to
177 // apply the results
178 const int mode=m_pano->getOptimizerSwitch();
179
181 if (optPano.getNrOfCtrlPoints() == 0)
182 {
183 hugin_utils::HuginMessageBox(_("There are no control points in the current configuration for the optimizer.\nPlease add control points before running the optimizer.\nOptimization canceled."),
184 _("Hugin"), wxICON_ERROR | wxOK, wxGetActiveWindow());
185 return;
186 };
187 // disable optimize button, so user can't click twice
188 hugin_utils::DisableWindow disableButton(XRCCTRL(*this, "optimize_panel_optimize", wxButton));
189
190 HuginBase::PanoramaOptions opts = optPano.getOptions();
191 switch(opts.getProjection())
192 {
196 break;
197 default:
198 // temporarily change to equirectangular
200 optPano.setOptions(opts);
201 break;
202 }
204 fill_set(allImg,0, imgs.size()-1);
205
206 char *p = setlocale(LC_ALL,NULL);
207 char *oldlocale = strdup(p);
208 setlocale(LC_ALL,"C");
210
211 if (mode & HuginBase::OPT_PAIR )
212 {
213 // temporarily disable PT progress dialog..
215 {
216 wxBusyCursor bc;
217 // run pairwise optimizer
219 }
220#ifdef DEBUG
221 // print optimized script to cout
222 DEBUG_DEBUG("panorama after autoOptimise():");
223 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
224#endif
225
227 // do global optimisation
229#ifdef DEBUG
230 // print optimized script to cout
231 DEBUG_DEBUG("panorama after optimise():");
232 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
233#endif
234
235 }
236 else
237 {
239 if (ignoreLineCp)
240 {
241 // store for later
242 originalCps = optPano.getCtrlPoints();
243 // remove all line cp
244 for (auto& cp : originalCps)
245 {
247 {
248 optCps.push_back(cp);
249 };
250 };
251 if (optCps.empty())
252 {
253 hugin_utils::HuginMessageBox(_("There are no control points in the current configuration for the optimizer.\nPlease add control points before running the optimizer.\nOptimization canceled."),
254 _("Hugin"), wxICON_ERROR | wxOK, wxGetActiveWindow());
255 return;
256 }
257 optPano.setCtrlPoints(optCps);
258 };
259 if (m_edit_cb->IsChecked() && mode==0)
260 {
261 // show and edit script..
262 std::ostringstream scriptbuf;
263 optPano.printPanoramaScript(scriptbuf, optPano.getOptimizeVector(), optPano.getOptions(), allImg, true);
264 // open a text dialog with an editor inside
265 wxDialog edit_dlg;
266 wxXmlResource::Get()->LoadDialog(&edit_dlg, this, "edit_script_dialog");
267 wxTextCtrl *txtCtrl=XRCCTRL(edit_dlg,"script_edit_text",wxTextCtrl);
268 txtCtrl->SetValue(wxString(scriptbuf.str().c_str(), *wxConvCurrent));
269
270 char * script = 0;
271 if (edit_dlg.ShowModal() == wxID_OK)
272 {
273 script = strdup(txtCtrl->GetValue().mb_str(*wxConvCurrent));
274 }
275 else
276 {
279 return;
280 }
282 free(script);
283 }
284 else
285 {
287 }
288#ifdef DEBUG
289 // print optimized script to cout
290 DEBUG_DEBUG("panorama after optimise():");
291 optPano.printPanoramaScript(std::cerr, optPano.getOptimizeVector(), optPano.getOptions(), allImg, false);
292#endif
293 }
294
297#ifdef __WXMSW__
298 // the progress window of the optimizer is marked for deletion
299 // but the final deletion happens only in the idle event
300 // so we need to process the event to really close the progress window
301 wxTheApp->ProcessIdle();
302#endif
303 // calculate control point errors and display text.
305 {
306 if (!originalCps.empty())
307 {
308 // restore all control points
309 optPano.setCtrlPoints(originalCps);
310 // because the line cp were removed we need to calculate the cp error again
312 };
315 );
316 }
317}
318
320{
321 double min;
322 double max;
323 double mean;
324 double var;
326
327 // check for HFOV lines. if smaller than 1 report a warning;
328 // also check for high distortion coefficients.
329 bool smallHFOV=false;
330 bool highDist = false;
331 const HuginBase::VariableMapVector & vars = pano.getVariables();
332 for (HuginBase::VariableMapVector::const_iterator it = vars.begin(); it != vars.end(); ++it)
333 {
334 if (const_map_get(*it,"v").getValue() < 1.0) smallHFOV = true;
335 if (fabs(const_map_get(*it,"a").getValue()) > 0.8) highDist = true;
336 if (fabs(const_map_get(*it,"b").getValue()) > 0.8) highDist = true;
337 if (fabs(const_map_get(*it,"c").getValue()) > 0.8) highDist = true;
338 }
339
341 int style=0;
342 if (smallHFOV)
343 {
344 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?"));
345 style = wxYES_NO;
346 }
347 else
348 {
349 if (highDist)
350 {
351 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?"),
352 mean, sqrt(var), max);
354 }
355 else
356 {
357 msg.Printf(_("Optimizer run finished.\nResults:\n average control point distance: %f\n standard deviation: %f\n maximum: %f\n\nApply the changes?"),
358 mean, sqrt(var), max);
360 }
361 };
362
364}
365
367{
368 DEBUG_TRACE("OnClose");
369 // do not close, just hide if we're not forced
370 if (event.CanVeto())
371 {
372 event.Veto();
373 Hide();
374 DEBUG_DEBUG("Hiding");
375 }
376 else
377 {
378 DEBUG_DEBUG("Closing");
379 Destroy();
380 }
381}
382
393
398
405
407{
409};
410
412{
413 m_ignore_line_cp->SetValue(noLineCp);
414};
415
416IMPLEMENT_DYNAMIC_CLASS(OptimizePanel, wxPanel)
417
418
420 : wxXmlResourceHandler()
421{
423}
424
426{
428
429 cp->Create(m_parentAsWindow,
430 GetID(),
431 GetPosition(), GetSize(),
432 GetStyle("style"),
433 GetName());
434
435 SetupWindow( cp);
436
437 return cp;
438}
439
441{
442 return IsOfClass(node, "OptimizePanel");
443}
444
445IMPLEMENT_DYNAMIC_CLASS(OptimizePanelXmlHandler, wxXmlResourceHandler)
GuiLevel
Definition GuiLevel.h:32
declaration of main image tree control
bool CheckLensStacks(HuginBase::Panorama *pano, bool allowCancel)
check, if lens and stacks are correctly linked shows message box with short information if not
some helper classes for graphes
some definitions to work with optimizer master switches
!! from PTOptimise.h 1951
void registerPTWXDlgFcn()
Definition PTWXDlg.cpp:178
void deregisterPTWXDlgFcn()
Definition PTWXDlg.cpp:185
Definition of PanoOperation class.
wraps around PTOptimizer
Utility calls into PanoTools using CPP interface.
static void calcCtrlPntsErrorStats(const PanoramaData &pano, double &min, double &max, double &mean, double &var, const int &imgNr=-1, const bool onlyActive=false, const bool ignoreLineCp=false)
virtual void run()
runs the algorithm.
Panorama image options.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
PanoramaOptions::ProjectionFormat getProjection() const
Model for a panorama.
Definition Panorama.h:153
void addObserver(PanoramaObserver *o)
add a panorama observer.
VariableMapVector getVariables() const
get variables of this panorama
Definition Panorama.cpp:118
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
const int getOptimizerSwitch() const
returns optimizer master switch
Definition Panorama.h:461
UIntSet getActiveImages() const
get active images
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
the main images tree control, used on images and optimizer tabs
Definition ImagesTree.h:37
HuginBase::UIntSet GetSelectedImages()
returns the selected images
void SetGuiLevel(GuiLevel newSetting)
sets the GuiLevel of the control
void Init(HuginBase::Panorama *pano)
initialization, connects all control with Panorama, register observer
void SetGroupMode(GroupMode newMode)
sets the group mode to given mode
void SetOptimizerMode()
sets to control into optimizer mode
void SetDisplayMode(DisplayMode newMode)
sets the display mode to given mode
void MarkActiveImages(const bool markActive)
sets the flag, if active/disabled image should be marked with different colour
static MainFrame * Get()
hack.. kind of a pseudo singleton...
const GuiLevel GetGuiLevel() const
Definition MainFrame.h:185
void SetOptimizeIgnoreLineCp(const bool ignoreLineCP)
sets the status of the "ignore line cp" menu item
void SetOptimizeOnlyActiveImages(const bool onlyActive)
sets the status of the "optimize only active images" menu item
virtual wxObject * DoCreateResource()
virtual bool CanHandle(wxXmlNode *node)
run the optimizer.
HuginBase::Panorama * m_pano
void SetGuiLevel(GuiLevel newGuiLevel)
bool AskApplyResult(wxWindow *activeWindow, const HuginBase::Panorama &pano)
virtual void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
receives notification about panorama changes
void OnCheckOnlyActiveImages(wxCommandEvent &e)
handle "only active images" checkbox
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
Delayed creation.
void OnClose(wxCloseEvent &e)
void SetOnlyActiveImages(const bool onlyActive)
for external setting of "only active image" checkbox
void OnOptimizeButton(wxCommandEvent &e)
run the optimizer
void Init(HuginBase::Panorama *pano)
void runOptimizer(const HuginBase::UIntSet &img, const bool ignoreLineCp)
wxCheckBox * m_edit_cb
wxCheckBox * m_ignore_line_cp
virtual void panoramaChanged(HuginBase::Panorama &pano)
receives notification about panorama changes
wxCheckBox * m_only_active_images_cb
ImagesTreeCtrl * m_images_tree_list
void OnCheckIgnoreLineCP(wxCommandEvent &e)
handle "ignore line cp" checkbox
void SetIgnoreLineCP(const bool noLineCp)
for external setting of "ignore line cp" checkbox
virtual ~OptimizePanel()
ImagesTreeCtrl * m_lens_tree_list
void OnReset(wxCommandEvent &e)
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
static GlobalCmdHist & getInstance()
Base class for all panorama commands.
Definition Command.h:39
update all variables & control points
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory,...
PanoOperation to reset image variables.
helper class, it disables the control/window in the constructor and automatically enables it back in ...
Definition wxutils.h:98
#define DEBUG_ASSERT(cond)
Definition utils.h:80
#define DEBUG_DEBUG(msg)
Definition utils.h:68
#define DEBUG_TRACE(msg)
Definition utils.h:67
void calcCtrlPointErrors(PanoramaData &pano)
Update the Ctrl Point errors without optimizing.
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
std::vector< VariableMap > VariableMapVector
std::vector< ControlPoint > CPVector
std::set< unsigned int > UIntSet
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition wxutils.cpp:176
include file for the hugin project
include file for the hugin project
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition stl_utils.h:81
const Map::mapped_type & const_map_get(const Map &m, const typename Map::key_type &key)
Definition stl_utils.h:110
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