Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImageVariableDialog.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This 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  * Lesser 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 
28 #include "base_wx/GraphTools.h"
29 #include "base_wx/wxPlatform.h"
30 #include "panoinc.h"
32 #include <map>
33 #include <string>
34 
35 #include "hugin/huginApp.h"
36 #include "base_wx/CommandHistory.h"
37 #include "base_wx/PanoCommand.h"
38 
40 {
41  // load our children. some children might need special
42  // initialization. this will be done later.
43  wxXmlResource::Get()->LoadDialog(this, parent, wxT("image_variables_dialog"));
44 
45  wxConfigBase * cfg = wxConfigBase::Get();
46  //position
47  int x = cfg->Read(wxT("/ImageVariablesDialog/positionX"),-1l);
48  int y = cfg->Read(wxT("/ImageVariablesDialog/positionY"),-1l);
49  if ( y >= 0 && x >= 0)
50  {
51  this->Move(x, y);
52  }
53  else
54  {
55  this->Move(0, 44);
56  };
57  m_pano=pano;
58  m_images=imgs;
59  m_popup=NULL;
60  InitValues();
61  // bind event handler
62  Bind(wxEVT_BUTTON, &ImageVariableDialog::OnOk, this, wxID_OK);
63  Bind(wxEVT_BUTTON, &ImageVariableDialog::OnHelp, this, wxID_HELP);
64  Bind(wxEVT_BUTTON, &ImageVariableDialog::OnShowDistortionGraph, this, XRCID("image_show_distortion_graph"));
65  Bind(wxEVT_BUTTON, &ImageVariableDialog::OnShowVignettingGraph, this, XRCID("image_show_vignetting_graph"));
66  Bind(wxEVT_BUTTON, &ImageVariableDialog::OnShowResponseGraph, this, XRCID("image_show_response_graph"));
67  Bind(wxEVT_CHOICE, &ImageVariableDialog::OnResponseSelected, this, XRCID("image_variable_responseType"));
68 };
69 
71 {
72  wxConfigBase * cfg = wxConfigBase::Get();
73  wxPoint ps = this->GetPosition();
74  cfg->Write(wxT("/ImageVariablesDialog/positionX"), ps.x);
75  cfg->Write(wxT("/ImageVariablesDialog/positionY"), ps.y);
76  cfg->Flush();
77 };
78 
80 {
81  XRCCTRL(*this, "image_variable_notebook", wxNotebook)->SetSelection(i);
82 };
83 
84 wxTextCtrl* GetImageVariableControl(const wxWindow* parent, const char* varname)
85 {
86  return wxStaticCast(
87  parent->FindWindow(
88  wxXmlResource::GetXRCID(
89  wxString(wxT("image_variable_")).append(wxString(varname, wxConvLocal)).c_str()
90  )
91  ), wxTextCtrl
92  );
93 };
94 
96 {
97  if(m_images.empty())
98  {
99  return;
100  };
101  HuginBase::BaseSrcPanoImage::ResponseType responseType = m_pano->getImage(*m_images.begin()).getResponseType();
102  bool identical=true;
103 
104  for (HuginBase::UIntSet::const_iterator it = m_images.begin(); it != m_images.end() && identical; ++it)
105  {
106  identical=(responseType==m_pano->getImage(*it).getResponseType());
107  };
108  if(identical)
109  {
110  XRCCTRL(*this, "image_variable_responseType", wxChoice)->SetSelection(responseType);
111  };
112 
113  int degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigitsEdit"),3);
114  int pixelDigits = wxConfigBase::Get()->Read(wxT("/General/PixelFractionalDigitsEdit"),2);
115  int distDigitsEdit = wxConfigBase::Get()->Read(wxT("/General/DistortionFractionalDigitsEdit"),5);
116 
118 
119  for (const char** varname = m_varNames; *varname != 0; ++varname)
120  {
121  // update parameters
122  int ndigits = distDigitsEdit;
123  if (strcmp(*varname, "y") == 0 || strcmp(*varname, "p") == 0 ||
124  strcmp(*varname, "r") == 0 || strcmp(*varname, "TrX") == 0 ||
125  strcmp(*varname, "TrY") == 0 || strcmp(*varname, "TrZ") == 0 )
126  {
127  ndigits=degDigits;
128  };
129  if (strcmp(*varname, "v") == 0 || strcmp(*varname, "d") == 0 ||
130  strcmp(*varname, "e") == 0 )
131  {
132  ndigits = pixelDigits;
133  }
134  double val=const_map_get(imgVarVector[*m_images.begin()],*varname).getValue();
135  bool identical=true;
136  for(HuginBase::UIntSet::const_iterator it=m_images.begin();it!=m_images.end() && identical;++it)
137  {
138  identical=(val==const_map_get(imgVarVector[*it],*varname).getValue());
139  };
140  if(identical)
141  {
142  GetImageVariableControl(this, *varname)->SetValue(hugin_utils::doubleTowxString(val,ndigits));
143  };
144  };
145  wxCommandEvent dummy;
146  OnResponseSelected(dummy);
147 };
148 
150 {
151  // translation
152  XRCCTRL(*this, "image_variable_text_translation", wxStaticText)->Show(newLevel==GUI_EXPERT);
153  XRCCTRL(*this, "image_variable_text_translation_x", wxStaticText)->Show(newLevel==GUI_EXPERT);
154  XRCCTRL(*this, "image_variable_text_translation_y", wxStaticText)->Show(newLevel==GUI_EXPERT);
155  XRCCTRL(*this, "image_variable_text_translation_z", wxStaticText)->Show(newLevel==GUI_EXPERT);
156  XRCCTRL(*this, "image_variable_text_translation_Tpy", wxStaticText)->Show(newLevel==GUI_EXPERT);
157  XRCCTRL(*this, "image_variable_text_translation_Tpp", wxStaticText)->Show(newLevel==GUI_EXPERT);
158  XRCCTRL(*this, "image_variable_TrX", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
159  XRCCTRL(*this, "image_variable_TrY", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
160  XRCCTRL(*this, "image_variable_TrZ", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
161  XRCCTRL(*this, "image_variable_Tpy", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
162  XRCCTRL(*this, "image_variable_Tpp", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
163  // shear
164  XRCCTRL(*this, "image_variable_text_shear", wxStaticText)->Show(newLevel==GUI_EXPERT);
165  XRCCTRL(*this, "image_variable_text_shear_g", wxStaticText)->Show(newLevel==GUI_EXPERT);
166  XRCCTRL(*this, "image_variable_text_shear_t", wxStaticText)->Show(newLevel==GUI_EXPERT);
167  XRCCTRL(*this, "image_variable_g", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
168  XRCCTRL(*this, "image_variable_t", wxTextCtrl)->Show(newLevel==GUI_EXPERT);
169 };
170 
172 {
173  std::vector<PanoCommand::PanoCommand*> commands;
174  HuginBase::VariableMap varMap;
175  for (const char** varname = m_varNames; *varname != 0; ++varname)
176  {
177  wxString s=GetImageVariableControl(this, *varname)->GetValue();
178  if(!s.empty())
179  {
180  double val;
181  if(hugin_utils::str2double(s,val))
182  {
183  if(strcmp(*varname, "v")==0)
184  {
185  if (val < 0.05)
186  {
187  wxMessageBox(_("The horizontal field of view must be positive."),
188 #ifdef __WXMSW__
189  _("Hugin"),
190 #else
191  wxT(""),
192 #endif
193  wxICON_EXCLAMATION | wxOK);
194  return false;
195  };
196  switch(m_pano->getImage(*m_images.begin()).getProjection())
197  {
199  if(val>179)
200  {
201  val=179;
202  };
203  break;
205  if(val>190)
206  {
207  if(wxMessageBox(
208  wxString::Format(_("You have given a field of view of %.2f degrees.\n But the orthographic projection is limited to a field of view of 180 degress.\nDo you want still use that high value?"), val),
209 #ifdef __WXMSW__
210  _("Hugin"),
211 #else
212  wxT(""),
213 #endif
214  wxICON_EXCLAMATION | wxYES_NO)==wxNO)
215  {
216  return false;
217  };
218  };
219  break;
220  default:
221  break;
222  };
223  };
224  varMap.insert(std::make_pair(std::string(*varname), HuginBase::Variable(std::string(*varname), val)));
225  }
226  else
227  {
228  wxLogError(_("Value must be numeric."));
229  return false;
230  };
231  };
232  };
233  int sel=XRCCTRL(*this, "image_variable_responseType", wxChoice)->GetSelection();
234  if(sel!=wxNOT_FOUND)
235  {
236  std::vector<HuginBase::SrcPanoImage> SrcImgs;
237  for (HuginBase::UIntSet::const_iterator it=m_images.begin(); it!=m_images.end(); ++it)
238  {
240  img.setResponseType((HuginBase::SrcPanoImage::ResponseType)sel);
241  SrcImgs.push_back(img);
242  }
243  commands.push_back(new PanoCommand::UpdateSrcImagesCmd( *m_pano, m_images, SrcImgs ));
244  }
245  if(!varMap.empty())
246  {
247  for(HuginBase::UIntSet::const_iterator it=m_images.begin();it!=m_images.end();++it)
248  {
249  commands.push_back(
251  );
252  };
253  };
254  if(!commands.empty())
255  {
257  return true;
258  }
259  else
260  {
261  return false;
262  };
263 };
264 
265 void ImageVariableDialog::OnOk(wxCommandEvent & e)
266 {
267  if(ApplyNewVariables())
268  {
269  e.Skip();
270  };
271 };
272 
273 void ImageVariableDialog::OnHelp(wxCommandEvent & e)
274 {
275  // open help on appropriate page
276  switch(XRCCTRL(*this, "image_variable_notebook", wxNotebook)->GetSelection())
277  {
278  //lens parameters
279  case 1:
280  MainFrame::Get()->DisplayHelp(wxT("Lens_correction_model.html"));
281  break;
282  case 2:
283  MainFrame::Get()->DisplayHelp(wxT("Vignetting.html"));
284  break;
285  case 3:
286  MainFrame::Get()->DisplayHelp(wxT("Camera_response_curve.html"));
287  break;
288  default:
289  MainFrame::Get()->DisplayHelp(wxT("Image_positioning_model.html"));
290  break;
291  };
292 };
293 
295 {
296  const bool showResponseParam = XRCCTRL(*this, "image_variable_responseType", wxChoice)->GetSelection() == 0;
297  wxTextCtrl* control = XRCCTRL(*this, "image_variable_Ra", wxTextCtrl);
298  control->Enable(showResponseParam);
299  control->Show(showResponseParam);
300  control = XRCCTRL(*this, "image_variable_Rb", wxTextCtrl);
301  control->Enable(showResponseParam);
302  control->Show(showResponseParam);
303  control = XRCCTRL(*this, "image_variable_Rc", wxTextCtrl);
304  control->Enable(showResponseParam);
305  control->Show(showResponseParam);
306  control = XRCCTRL(*this, "image_variable_Rd", wxTextCtrl);
307  control->Enable(showResponseParam);
308  control->Show(showResponseParam);
309  control = XRCCTRL(*this, "image_variable_Re", wxTextCtrl);
310  control->Enable(showResponseParam);
311  control->Show(showResponseParam);
312 };
313 
314 const char *ImageVariableDialog::m_varNames[] = { "y", "p", "r", "TrX", "TrY", "TrZ", "Tpy", "Tpp",
315  "v", "a", "b", "c", "d", "e", "g", "t",
316  "Eev", "Er", "Eb",
317  "Vb", "Vc", "Vd", "Vx", "Vy",
318  "Ra", "Rb", "Rc", "Rd", "Re", 0};
319 
321 {
322  wxString stringa=GetImageVariableControl(this, "a")->GetValue();
323  wxString stringb=GetImageVariableControl(this, "b")->GetValue();
324  wxString stringc=GetImageVariableControl(this, "c")->GetValue();
325  if(stringa.empty() || stringb.empty() || stringc.empty())
326  {
327  wxBell();
328  return;
329  };
330  std::vector<double> radialDist(4 ,0);
331  if(!hugin_utils::str2double(stringa, radialDist[0]) || !hugin_utils::str2double(stringb, radialDist[1]) || !hugin_utils::str2double(stringc, radialDist[2]))
332  {
333  wxBell();
334  return;
335  };
336  radialDist[3] = 1 - radialDist[0] - radialDist[1] - radialDist[2];
337 
338  //create transformation
340  srcImage.setSize(m_pano->getImage(*(m_images.begin())).getSize());
341  // set projection to rectilinear, just in case, it should be the default value
342  srcImage.setProjection(HuginBase::SrcPanoImage::RECTILINEAR);
343  srcImage.setRadialDistortion(radialDist);
344 
345  delete m_popup;
346  //show popup
348  wxWindow *button = (wxWindow*) e.GetEventObject();
349  wxPoint pos=button->ClientToScreen(wxPoint(0,0));
350  m_popup->Position(pos, button->GetSize());
351  m_popup->Popup();
352 };
353 
355 {
356  wxString stringVb=GetImageVariableControl(this, "Vb")->GetValue();
357  wxString stringVc=GetImageVariableControl(this, "Vc")->GetValue();
358  wxString stringVd=GetImageVariableControl(this, "Vd")->GetValue();
359  if(stringVb.empty() || stringVc.empty() || stringVd.empty())
360  {
361  wxBell();
362  return;
363  };
364  std::vector<double> vigCorr(4,0);
365  vigCorr[0]=1.0;
366  if(!hugin_utils::str2double(stringVb, vigCorr[1]) || !hugin_utils::str2double(stringVc, vigCorr[2]) || !hugin_utils::str2double(stringVd, vigCorr[3]))
367  {
368  wxBell();
369  return;
370  };
371  delete m_popup;
372  wxGraphTools::Graph graph(300, 200, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
373  graph.SetChartArea(10, 10, 290, 190);
374  graph.SetChartDisplay(0, 0.8, 1, 1);
375  graph.DrawGrid(6, 6);
376 
377  //create ResponseTransform with vignetting only
379  srcImage.setRadialVigCorrCoeff(vigCorr);
380 #define NRPOINTS 100
381  srcImage.setSize(vigra::Size2D(2*NRPOINTS, 2*NRPOINTS));
383  transform.enforceMonotonicity();
384 
385  //now calc vignetting curve
386  std::vector<hugin_utils::FDiff2D> points;
387 #define NRPOINTS 100
388  for(size_t i=0; i<=NRPOINTS; i++)
389  {
390  points.push_back(hugin_utils::FDiff2D(i/double(NRPOINTS),transform(1.0, hugin_utils::FDiff2D(NRPOINTS-i, NRPOINTS-i))));
391  };
392  graph.DrawLine(points, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), 2);
393 
394  //display popup
395  m_popup = new wxGraphTools::GraphPopupWindow(this, graph.GetGraph());
396  wxWindow *button = (wxWindow*) e.GetEventObject();
397  wxPoint pos=button->ClientToScreen(wxPoint(0,0));
398  m_popup->Position(pos, button->GetSize());
399  m_popup->Popup();
400 };
401 
403 {
404  HuginBase::SrcPanoImage::ResponseType responseType=(HuginBase::SrcPanoImage::ResponseType)XRCCTRL(*this, "image_variable_responseType", wxChoice)->GetSelection();
405  wxString stringRa=GetImageVariableControl(this, "Ra")->GetValue();
406  wxString stringRb=GetImageVariableControl(this, "Rb")->GetValue();
407  wxString stringRc=GetImageVariableControl(this, "Rc")->GetValue();
408  wxString stringRd=GetImageVariableControl(this, "Rd")->GetValue();
409  wxString stringRe=GetImageVariableControl(this, "Re")->GetValue();
410  if(stringRa.empty() || stringRb.empty() || stringRc.empty() || stringRd.empty() || stringRe.empty())
411  {
412  wxBell();
413  return;
414  };
415  double Ra, Rb, Rc, Rd, Re;
416  if(!hugin_utils::str2double(stringRa, Ra) || !hugin_utils::str2double(stringRb, Rb) || !hugin_utils::str2double(stringRc, Rc) ||
417  !hugin_utils::str2double(stringRd, Rd) || !hugin_utils::str2double(stringRe, Re))
418  {
419  wxBell();
420  return;
421  };
422  delete m_popup;
423  wxGraphTools::Graph graph(300, 200, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
424  graph.SetChartArea(10, 10, 290, 190);
425  graph.SetChartDisplay(0, 0, 1, 1);
426  graph.DrawGrid(6, 6);
427  switch(responseType)
428  {
430  {
431  //draw standard EMOR curve
432  std::vector<float> emor(5, 0.0);
433  std::vector<double> outLutStd;
434  vigra_ext::EMoR::createEMoRLUT(emor, outLutStd);
436  graph.SetChartDisplay(0, 0, outLutStd.size()-1.0, 1.0);
437  std::vector<hugin_utils::FDiff2D> points;
438  for(size_t i=0; i<outLutStd.size(); i++)
439  {
440  points.push_back(hugin_utils::FDiff2D(i, outLutStd[i]));
441  };
442  graph.DrawLine(points, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), 1);
443  outLutStd.clear();
444  points.clear();
445  // now draw our curve
446  emor[0]=Ra;
447  emor[1]=Rb;
448  emor[2]=Rc;
449  emor[3]=Rd;
450  emor[4]=Re;
451  std::vector<double> outLut;
452  vigra_ext::EMoR::createEMoRLUT(emor, outLut);
454  graph.SetChartDisplay(0, 0, outLut.size()-1.0, 1.0);
455  for(size_t i=0; i<outLut.size(); i++)
456  {
457  points.push_back(hugin_utils::FDiff2D(i, outLut[i]));
458  };
459  graph.DrawLine(points, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), 2);
460  };
461  break;
463  default:
464  {
465  std::vector<hugin_utils::FDiff2D> points;
466  points.push_back(hugin_utils::FDiff2D(0, 0));
467  points.push_back(hugin_utils::FDiff2D(1, 1));
468  graph.DrawLine(points, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), 2);
469  };
470  break;
471  };
472  //show popup
473  m_popup = new wxGraphTools::GraphPopupWindow(this, graph.GetGraph());
474  wxWindow *button = (wxWindow*) e.GetEventObject();
475  wxPoint pos=button->ClientToScreen(wxPoint(0,0));
476  m_popup->Position(pos, button->GetSize());
477  m_popup->Popup();
478 };
void DisplayHelp(wxString section=wxEmptyString)
call help browser with given file
Definition: MainFrame.cpp:1483
update source images
Definition: PanoCommand.h:404
#define NRPOINTS
void OnShowDistortionGraph(wxCommandEvent &e)
shows a popup with distortion graph
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
void SetGuiLevel(GuiLevel newLevel)
sets the GuiLevel
radiometric transformation, includes exposure, vignetting and white balance.
void OnShowVignettingGraph(wxCommandEvent &e)
shows a popup with vignetting graph
void enforceMonotonicity(LUT &lut)
enforce monotonicity of an array (mostly used for lookup tables)
Definition: lut.h:87
wxString doubleTowxString(double d, int digits)
Definition: wxPlatform.cpp:31
void SelectTab(size_t i)
selects the tab with index i
a variable has a value and a name.
include file for the hugin project
update variables of a single image
Definition: PanoCommand.h:160
simple popup to show graph
Definition: GraphTools.h:38
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
Definition: ROIImage.h:300
void DrawGrid(size_t linesX, size_t linesY)
draws the grid with linesX lines in x-direction and linexY lines in y-direction
Definition: GraphTools.cpp:145
const Map::mapped_type & const_map_get(const Map &m, const typename Map::key_type &key)
Definition: stl_utils.h:110
void OnResponseSelected(wxCommandEvent &e)
response type changed
PanoCommand to combine other PanoCommands.
Definition: PanoCommand.h:39
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
std::vector< VariableMap > VariableMapVector
Model for a panorama.
Definition: Panorama.h:152
empirical model of response
Definition: SrcPanoImage.h:100
wxGraphTools::GraphPopupWindow * m_popup
VariableMapVector getVariables() const
get variables of this panorama
Definition: Panorama.cpp:118
Definition of dialog to edit image variables.
void OnHelp(wxCommandEvent &e)
shows the help
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2153
wxTextCtrl * GetImageVariableControl(const wxWindow *parent, const char *varname)
void SetChartArea(int left, int top, int right, int bottom)
set where to draw the chart on the bitmap
Definition: GraphTools.cpp:125
void SetChartDisplay(double xmin, double ymin, double xmax, double ymax)
set the real dimension of the chart
Definition: GraphTools.cpp:136
bool ApplyNewVariables()
applies the changed variables to the Panorama class, using CommandHistory
static GlobalCmdHist & getInstance()
void DrawLine(std::vector< hugin_utils::FDiff2D > points, wxColour colour, int penWidth=1)
draws a line with the coordinates given in points
Definition: GraphTools.cpp:161
void OnOk(wxCommandEvent &e)
Saves current state of all checkboxes when closing dialog with Ok.
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
void createEMoRLUT(const std::vector< float > &params, VECTOR &lut)
Definition: emor.h:44
std::map< std::string, Variable > VariableMap
help class to draw charts
Definition: GraphTools.h:51
~ImageVariableDialog()
destructor, saves position
void OnShowResponseGraph(wxCommandEvent &e)
shows a popup with response graph
wxBitmap GetDistortionGraph(const HuginBase::SrcPanoImage &srcImage)
return wxBitmap with graph of distortion for given SrcPanoImage
Definition: GraphTools.cpp:193
void setSize(vigra::Size2D val)
Set the image size in pixels.
platform/compiler specific stuff.
ImageVariableDialog(wxWindow *parent, HuginBase::Panorama *pano, HuginBase::UIntSet imgs)
Constructor, read from xrc ressource; restore last uses settings and position.
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
GuiLevel
Definition: GuiLevel.h:31
const wxBitmap GetGraph() const
Definition: GraphTools.cpp:178
static const char * m_varNames[]
All variables of a source image.
Definition: SrcPanoImage.h:194
HuginBase::UIntSet m_images
HuginBase::Panorama * m_pano
void InitValues()
copy the variables from Panorama to dialog