27 #include "hugin_config.h"
56 #include "vigra/cornerdetection.hxx"
57 #include "vigra/localminmax.hxx"
67 EVT_COMBOBOX(XRCID("cp_editor_left_choice"),
CPEditorPanel::OnLeftChoiceChange )
68 EVT_COMBOBOX(XRCID("cp_editor_right_choice"),
CPEditorPanel::OnRightChoiceChange )
69 EVT_LIST_ITEM_SELECTED(XRCID("cp_editor_cp_list"),
CPEditorPanel::OnCPListSelect)
70 EVT_LIST_ITEM_DESELECTED(XRCID("cp_editor_cp_list"),
CPEditorPanel::OnCPListDeselect)
71 EVT_LIST_COL_END_DRAG(XRCID("cp_editor_cp_list"),
CPEditorPanel::OnColumnWidthChange)
72 EVT_LIST_COL_CLICK(XRCID("cp_editor_cp_list"),
CPEditorPanel::OnColumnHeaderClick)
73 EVT_CHOICE(XRCID("cp_editor_choice_zoom"),
CPEditorPanel::OnZoom)
74 EVT_TEXT_ENTER(XRCID("cp_editor_x1"),
CPEditorPanel::OnTextPointChange )
75 EVT_TEXT_ENTER(XRCID("cp_editor_y1"),
CPEditorPanel::OnTextPointChange )
76 EVT_TEXT_ENTER(XRCID("cp_editor_x2"),
CPEditorPanel::OnTextPointChange )
77 EVT_TEXT_ENTER(XRCID("cp_editor_y2"),
CPEditorPanel::OnTextPointChange )
78 EVT_CHOICE(XRCID("cp_editor_mode"),
CPEditorPanel::OnTextPointChange )
80 EVT_BUTTON(XRCID("cp_editor_delete"),
CPEditorPanel::OnDeleteButton)
81 EVT_BUTTON(XRCID("cp_editor_add"),
CPEditorPanel::OnAddButton)
82 EVT_BUTTON(XRCID("cp_editor_previous_img"),
CPEditorPanel::OnPrevImg)
83 EVT_BUTTON(XRCID("cp_editor_next_img"),
CPEditorPanel::OnNextImg)
84 EVT_BUTTON(XRCID("cp_editor_finetune_button"),
CPEditorPanel::OnFineTuneButton)
85 EVT_BUTTON(XRCID("cp_editor_action_button"),
CPEditorPanel::OnActionButton)
86 EVT_MENU(XRCID("cp_menu_create_cp"),
CPEditorPanel::OnActionSelectCreate)
87 EVT_MENU(XRCID("cp_menu_celeste"),
CPEditorPanel::OnActionSelectCeleste)
88 EVT_MENU(XRCID("cp_menu_clean_cp"),
CPEditorPanel::OnActionSelectCleanCP)
89 EVT_CHECKBOX(XRCID("cp_editor_show_lines"),
CPEditorPanel::OnShowLinesCheckbox)
103 const wxString& name)
106 if (! wxPanel::Create(parent,
id, pos, size, style, name) ) {
121 wxXmlResource::Get()->LoadPanel(
this, wxT(
"cp_editor_panel"));
122 wxPanel * panel = XRCCTRL(*
this,
"cp_editor_panel", wxPanel);
124 wxBoxSizer *topsizer =
new wxBoxSizer( wxVERTICAL );
125 topsizer->Add(panel, 1, wxEXPAND, 0);
143 m_cpList = XRCCTRL(*
this,
"cp_editor_cp_list", wxListCtrl);
145 m_cpList->InsertColumn( 0, _(
"#"), wxLIST_FORMAT_RIGHT, 35);
146 m_cpList->InsertColumn( 1, _(
"left x"), wxLIST_FORMAT_RIGHT, 65);
147 m_cpList->InsertColumn( 2, _(
"left y"), wxLIST_FORMAT_RIGHT, 65);
148 m_cpList->InsertColumn( 3, _(
"right x"), wxLIST_FORMAT_RIGHT, 65);
149 m_cpList->InsertColumn( 4, _(
"right y"), wxLIST_FORMAT_RIGHT, 65);
150 m_cpList->InsertColumn( 5, _(
"Alignment"), wxLIST_FORMAT_LEFT,110 );
151 m_cpList->InsertColumn( 6, _(
"Distance"), wxLIST_FORMAT_RIGHT, 110);
154 wxConfigBase* config = wxConfig::Get();
155 for (
int j=0; j <
m_cpList->GetColumnCount() ; j++ )
158 int width = config->Read(wxString::Format( wxT(
"/CPEditorPanel/ColumnWidth%d"), j ), -1);
162 m_sortCol = config->Read(wxT(
"/CPEditorPanel/SortColumn"), -1);
163 m_sortAscending = config->Read(wxT(
"/CPEditorPanel/SortAscending"), 1) == 1 ?
true :
false;
170 m_x1Text = XRCCTRL(*
this,
"cp_editor_x1", wxTextCtrl);
172 m_y1Text = XRCCTRL(*
this,
"cp_editor_y1", wxTextCtrl);
174 m_x2Text = XRCCTRL(*
this,
"cp_editor_x2", wxTextCtrl);
176 m_y2Text = XRCCTRL(*
this,
"cp_editor_y2", wxTextCtrl);
180 m_addButton = XRCCTRL(*
this,
"cp_editor_add", wxButton);
181 m_delButton = XRCCTRL(*
this,
"cp_editor_delete", wxButton);
183 m_autoAddCB = XRCCTRL(*
this,
"cp_editor_auto_add", wxCheckBox);
185 m_fineTuneCB = XRCCTRL(*
this,
"cp_editor_fine_tune_check",wxCheckBox);
188 m_estimateCB = XRCCTRL(*
this,
"cp_editor_auto_estimate", wxCheckBox);
191 m_showLinesCB = XRCCTRL(*
this,
"cp_editor_show_lines", wxCheckBox);
194 m_actionButton = XRCCTRL(*
this,
"cp_editor_action_button", wxButton);
198 m_cp_ctrls = XRCCTRL(*
this,
"cp_controls_panel", wxPanel);
201 m_autoAddCB->SetValue(config->Read(wxT(
"/CPEditorPanel/autoAdd"),0l) != 0 );
202 m_fineTuneCB->SetValue(config->Read(wxT(
"/CPEditorPanel/autoFineTune"),1l) != 0 );
203 m_estimateCB->SetValue(config->Read(wxT(
"/CPEditorPanel/autoEstimate"),1l) != 0 );
204 m_showLinesCB->SetValue(config->Read(wxT(
"/CPEditorPanel/showLines"), 1l) != 0);
216 XRCCTRL(*
this,
"cp_editor_finetune_button", wxButton)->Disable();
218 XRCCTRL(*
this,
"cp_editor_choice_zoom", wxChoice)->Disable();
219 XRCCTRL(*
this,
"cp_editor_previous_img", wxButton)->Disable();
220 XRCCTRL(*
this,
"cp_editor_next_img", wxButton)->Disable();
225 wxCommandEvent dummy;
226 dummy.SetInt(XRCCTRL(*
this,
"cp_editor_choice_zoom",wxChoice)->GetSelection());
229 SetSizer( topsizer );
277 wxConfigBase* config = wxConfig::Get();
278 config->Write(wxT(
"/CPEditorPanel/autoAdd"),
m_autoAddCB->IsChecked() ? 1 : 0);
279 config->Write(wxT(
"/CPEditorPanel/autoFineTune"),
m_fineTuneCB->IsChecked() ? 1 : 0);
280 config->Write(wxT(
"/CPEditorPanel/autoEstimate"),
m_estimateCB->IsChecked() ? 1 : 0);
281 config->Write(wxT(
"/CPEditorPanel/showLines"),
m_showLinesCB->IsChecked() ? 1 : 0);
282 config->Write(wxT(
"/CPEditorPanel/SortColumn"),
m_sortCol);
283 config->Write(wxT(
"/CPEditorPanel/SortAscending"),
m_sortAscending ? 1 : 0);
293 if (imgNr == UINT_MAX) {
317 ImageCache::getInstance().softFlush();
325 if (imgNr == UINT_MAX) {
354 ImageCache::getInstance().softFlush();
366 if(m_leftImageNr<m_pano->getNrOfImages())
385 if(m_rightImageNr<m_pano->getNrOfImages())
425 #define SORTASCENDING(functionName, var) \
426 int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
428 HuginBase::CPointVector* data = (HuginBase::CPointVector*)(sortData);\
429 if (data->at(item1).second.var > data->at(item2).second.var)\
431 if (data->at(item1).second.var < data->at(item2).second.var)\
436 #define SORTDESCENDING(functionName, var) \
437 int wxCALLBACK functionName(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)\
439 HuginBase::CPointVector* data = (HuginBase::CPointVector*)(sortData); \
440 if (data->at(item1).second.var < data->at(item2).second.var)\
442 if (data->at(item1).second.var > data->at(item2).second.var)\
461 #undef SORTDESCENDING
552 }
else if (ev.GetEventObject() ==
m_rightImg){
583 const long selectedPoint =
m_cpList->FindItem(-1, nr);
586 m_cpList->SetItemState(selectedPoint, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
596 bool hor = std::abs(cp.
x1 - cp.
x2) > (std::abs(cp.
y1 - cp.
y2) * vertBias);
629 DEBUG_ERROR(
"invalid point number while moving point")
635 <<
" " << cp.
x2 <<
"," << cp.
y2);
704 if(!cpToRemove.empty())
736 bool hor = std::abs(p1.
x - p2.
x) > (std::abs(p1.
y - p2.
y) * vertBias);
800 if (selectedPoint != wxNOT_FOUND)
802 m_cpList->SetItemState(selectedPoint, 0, wxLIST_STATE_SELECTED);
814 DEBUG_TRACE(
"selectLocalPoint(" << LVpointNr <<
")");
825 m_x1Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
x1));
826 m_y1Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
y1));
827 m_x2Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
x2));
828 m_y2Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
y2));
832 const long selectedPoint =
m_cpList->FindItem(-1, LVpointNr);
833 if (scrollLeft && scrollRight)
837 m_cpList->SetItemState(selectedPoint, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
839 m_cpList->EnsureVisible(selectedPoint);
846 unsigned int localNr;
848 DEBUG_DEBUG(
"CPEditor::setGlobalPoint(" << globalNr <<
") found local point " << localNr);
851 DEBUG_ERROR(
"CPEditor::setGlobalPoint: point " << globalNr <<
" not found in currentPoints");
857 HuginBase::CPointVector::const_iterator it =
currentPoints.begin();
859 while(it !=
currentPoints.end() && (*it).first != globalNr) {
881 unsigned int thisImgNr,
885 unsigned int otherImgNr,
893 if (op.
x < (
int) pImg.getSize().width() && op.
x >= 0
894 && op.
y < (int) pImg.getSize().height() && op.
y >= 0)
900 MainFrame::Get()->SetStatusText(_(
"searching similar points..."),0);
918 }
catch (std::exception & e) {
919 wxMessageBox(wxString (e.what(), wxConvLocal), _(
"Error during Fine-tune"));
923 if (corrPoint.corrPos.x >= 0 && corrPoint.corrPos.y >= 0 && corrPoint.maxpos.x > 0 && corrPoint.maxpos.y > 0)
938 s1.Printf(_(
"Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f"),
939 corrPoint.maxAngle, corrPoint.maxi, corrPoint.curv.x, corrPoint.curv.y );
941 wxString s2 = s1 + wxT(
" -- ") + wxString(_(
"change points, or press right mouse button to add the pair"));
962 MainFrame::Get()->SetStatusText(_(
"Estimated point outside image"),0);
1004 bool hasNormalCP =
false;
1009 if (estimate && (thisImgNr != otherImgNr) && hasNormalCP) {
1011 thisImg, thisImgNr, THIS_POINT, THIS_POINT_RETRY,
1012 otherImg, otherImgNr, OTHER_POINT, OTHER_POINT_RETRY);
1021 bool hasNormalCP =
false;
1026 if (estimate && (thisImgNr != otherImgNr) && hasNormalCP) {
1028 thisImg, thisImgNr, THIS_POINT, THIS_POINT_RETRY,
1029 otherImg, otherImgNr, OTHER_POINT, OTHER_POINT_RETRY);
1044 double sAreaPercent = wxConfigBase::Get()->Read(wxT(
"/Finetune/SearchAreaPercent"),
1047 bool corrOk =
false;
1049 vigra::Diff2D newPoint_round = newPoint.
toDiff2D();
1058 }
catch (std::exception & e) {
1059 wxMessageBox(wxString (e.what(), wxConvLocal), _(
"Error during Fine-tune"));
1083 s1.Printf(_(
"Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f"),
1086 corrMsg = s1 + wxT(
" -- ") + wxString(_(
"change points, or press right mouse button to add the pair"));
1119 if (corrMsg != wxT(
"")) {
1139 imgMod.
setSize(img.getSize());
1140 imgMod.setProjection(img.getProjection());
1141 imgMod.setHFOV(img.getHFOV());
1178 neededHFOV = 2.0 * (x1 - x2);
1183 neededHFOV = 2.0 * (360 - x2 + x1);
1186 if (neededHFOV > 90)
1198 neededHFOV = 2.0 * (x2 - x1);
1203 neededHFOV = 2.0 * (360 + x2 - x1);
1206 if (neededHFOV > 90)
1218 vigra::Diff2D templPos,
int templSize,
1220 vigra::Diff2D searchPos,
int sWidth)
1224 wxConfigBase *cfg = wxConfigBase::Get();
1234 if (templ.getProjection() == search.getProjection()
1235 && templ.getHFOV() < 65 && search.getHFOV() < 65
1236 && fabs(templ.getHFOV() - search.getHFOV()) < 5)
1239 if (rotatingFinetune)
1242 searchImg, searchPos, sWidth, startAngle, stopAngle, nSteps);
1246 res =
vigra_ext::PointFineTune(templImg, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), templPos, templSize,
1247 searchImg, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), searchPos, sWidth);
1255 double templHFOV = 0;
1256 double searchHFOV = 0;
1262 if (templHFOV < 0 || searchHFOV < 0)
1279 double templX, templY, searchX, searchY;
1287 vigra::UInt8RGBImage searchImgMod(opts.
getSize());
1288 vigra::BImage alpha(opts.
getSize());
1294 vigra::Rect2D rect(templPointInt.x - templSize - 2, templPointInt.y - templSize - 2,
1295 templPointInt.x + templSize + 2, templPointInt.y + templSize + 2);
1296 rect &= vigra::Rect2D(opts.
getSize());
1298 vigra::UInt8RGBImage templImgMod(opts.
getSize());
1301 #if defined DEBUG_EXPORT_FINE_TUNE_REMAPPING
1303 vigra::ImageExportInfo templExport(
"template_remapped.tif");
1304 vigra::exportImage(
srcImageRange(templImgMod), templExport.setPixelType(
"UINT8"));
1305 vigra::ImageExportInfo searchExport(
"search_remapped.tif");
1306 vigra::exportImage(
srcImageRange(searchImgMod), searchExport.setPixelType(
"UINT8"));
1324 const vigra::Diff2D & tmplPoint,
1326 unsigned int subjImgNr,
1331 DEBUG_TRACE(
"tmpl img nr: " << tmplImgNr <<
" corr src: "
1333 if (tmplImgNr == subjImgNr)
1338 const double distance = (tmplPoint - o_subjPoint.
toDiff2D()).magnitude();
1339 if (distance < sWidth)
1341 sWidth = 0.9 * distance;
1343 if (sWidth < 1.1 * templSize)
1345 MainFrame::Get()->SetStatusText(_(
"Distance between line control points too short, skipping fine-tune."));
1350 MainFrame::Get()->SetStatusText(_(
"searching similar points..."),0);
1353 wxConfigBase::Get()->Read(wxT(
"/Finetune/CorrThreshold"),&corrThresh,
1358 if (tmplImgNr != subjImgNr)
1376 MainFrame::Get()->SetStatusText(wxString::Format(_(
"Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f"),
1381 wxMessageDialog dlg(
this,
1382 _(
"No similar point found."),
1388 wxICON_ERROR | wxOK);
1389 dlg.SetExtendedMessage(_(
"An internal transformation went wrong.\nCheck that the point is inside the image."));
1393 if (res.
maxi < corrThresh || res.
curv.
x < curvThresh || res.
curv.
y < curvThresh )
1396 wxMessageDialog dlg(
this,
1397 _(
"No similar point found."),
1403 wxICON_ERROR | wxOK);
1404 dlg.SetExtendedMessage(wxString::Format(_(
"Check the similarity visually.\nCorrelation coefficient (%.3f) is lower than the threshold set in the preferences."),
1417 DEBUG_DEBUG(
"mode choice: " << nGui <<
" entries, required: " << nPano);
1423 for (
int i = nGui-1; i > nPano-1; --i) {
1430 }
else if (nGui < nPano) {
1433 m_cpModeChoice->SetString(nGui-1, wxString::Format(_(
"Line %d"), nGui-1));
1435 for (
int i = nGui; i < nPano-1; i++) {
1454 item.SetText(_(
"Correlation"));
1458 item.SetText(_(
"Distance"));
1470 DEBUG_TRACE(
"nrImages:" << nrImages <<
" nrTabs:" << nrTabs);
1487 XRCCTRL(*
this,
"cp_editor_finetune_button", wxButton)->Disable();
1489 XRCCTRL(*
this,
"cp_editor_choice_zoom", wxChoice)->Disable();
1490 XRCCTRL(*
this,
"cp_editor_previous_img", wxButton)->Disable();
1491 XRCCTRL(*
this,
"cp_editor_next_img", wxButton)->Disable();
1503 XRCCTRL(*
this,
"cp_editor_finetune_button", wxButton)->Enable();
1505 XRCCTRL(*
this,
"cp_editor_choice_zoom", wxChoice)->Enable();
1506 XRCCTRL(*
this,
"cp_editor_previous_img", wxButton)->Enable();
1507 XRCCTRL(*
this,
"cp_editor_next_img", wxButton)->Enable();
1511 ImageCache::getInstance().softFlush();
1515 for (
unsigned int i=0; i < ((nrTabs < nrImages)? nrTabs: nrImages); i++) {
1517 m_leftChoice->SetString(i, wxString::Format(wxT(
"%d"), i) + wxT(
". - ") + fileName.GetFullName());
1518 m_rightChoice->SetString(i, wxString::Format(wxT(
"%d"), i) + wxT(
". - ") + fileName.GetFullName());
1526 if (nrTabs < nrImages)
1528 for (
unsigned int i=nrTabs; i < nrImages; i++)
1531 m_leftChoice->Append(wxString::Format(wxT(
"%d"), i) + wxT(
". - ") + fileName.GetFullName());
1532 m_rightChoice->Append(wxString::Format(wxT(
"%d"), i) + wxT(
". - ") + fileName.GetFullName());
1538 if (nrTabs > nrImages)
1546 for (
int i=nrTabs-1; i >= (int)nrImages; i--) {
1575 for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it) {
1576 unsigned int imgNr = *it;
1630 if (update || nrImages == 0) {
1674 HuginBase::CPVector::size_type i = 0;
1677 for (HuginBase::CPVector::size_type index = 0; index < controlPoints.size(); ++index)
1698 unsigned int selectedItem = UINT_MAX;
1699 long selectedCP = -1;
1700 for (
int i = 0; i <
m_cpList->GetItemCount(); i++)
1702 if (
m_cpList->GetItemState( i, wxLIST_STATE_SELECTED))
1704 selectedItem = (
unsigned int) i;
1705 selectedCP =
m_cpList->GetItemData(i);
1715 long item =
m_cpList->InsertItem(i, wxString::Format(wxT(
"%d"), i), -1);
1718 m_cpList->SetItem(i,1,wxString::Format(wxT(
"%.2f"),p.
x1));
1719 m_cpList->SetItem(i,2,wxString::Format(wxT(
"%.2f"),p.
y1));
1720 m_cpList->SetItem(i,3,wxString::Format(wxT(
"%.2f"),p.
x2));
1721 m_cpList->SetItem(i,4,wxString::Format(wxT(
"%.2f"),p.
y2));
1728 mode = _(
"vert. Line");
1731 mode = _(
"horiz. Line");
1734 mode = wxString::Format(_(
"Line %d"), p.
mode);
1738 m_cpList->SetItem(i,6,wxString::Format(wxT(
"%.2f"),p.
error));
1742 if (selectedItem <= (
unsigned int)
m_cpList->GetItemCount() && !newPair &&
m_cpList->GetItemCount() > 0)
1749 long selected =
m_cpList->FindItem(-1, selectedCP);
1750 m_cpList->SetItemState(selected, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
1757 if (selectedItem == (
unsigned int)
m_cpList->GetItemCount())
1760 selectedItem =
m_cpList->GetItemCount() - 1;
1762 m_cpList->SetItemState(selectedItem, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
1763 m_cpList->EnsureVisible(selectedItem);
1769 m_x1Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
x1));
1770 m_y1Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
y1));
1771 m_x2Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
x2));
1772 m_y2Text->SetValue(wxString::Format(wxT(
"%.2f"),p.
y2));
1782 for (
int j=0; j <
m_cpList->GetColumnCount() ; j++ )
1786 int width = wxConfigBase::Get()->Read(wxString::Format( wxT(
"/CPEditorPanel/ColumnWidth%d"), j ), -1);
1788 m_cpList->SetColumnWidth(j, width);
1797 XRCCTRL(*
this,
"cp_editor_finetune_button", wxButton)->Enable(state);
1812 wxLIST_STATE_SELECTED);
1817 const unsigned int nr =
m_cpList->GetItemData(item);
1822 double oldValue=cp.x1;
1872 DEBUG_TRACE(
"OnLeftChoiceChange() to " << e.GetSelection());
1880 DEBUG_TRACE(
"OnRightChoiceChange() to " << e.GetSelection());
1887 int t = ev.GetIndex();
1925 const wxSize leftSize =
m_leftImg->GetClientSize();
1926 const wxSize rightSize =
m_rightImg->GetClientSize();
1936 switch (e.GetSelection()) {
1977 m_leftImg->Scroll(leftX*factor - leftSize.GetWidth() / 2, leftY*factor - leftSize.GetHeight() / 2);
1978 m_rightImg->Scroll(rightX*factor - rightSize.GetWidth() / 2, rightY*factor - rightSize.GetHeight() / 2);
1986 <<
" origin: id:" << e.GetId() <<
" obj: "
1987 << e.GetEventObject());
1989 if (e.m_keyCode == WXK_DELETE){
2000 wxLIST_STATE_SELECTED);
2012 }
else if (e.m_keyCode ==
'0') {
2013 wxCommandEvent dummy;
2016 XRCCTRL(*
this,
"cp_editor_choice_zoom",wxChoice)->SetSelection(1);
2017 }
else if (e.m_keyCode ==
'1') {
2018 wxCommandEvent dummy;
2021 XRCCTRL(*
this,
"cp_editor_choice_zoom",wxChoice)->SetSelection(0);
2022 }
else if (e.m_keyCode ==
'2') {
2023 wxCommandEvent dummy;
2026 XRCCTRL(*
this,
"cp_editor_choice_zoom",wxChoice)->SetSelection(2);
2027 }
else if (e.CmdDown() && e.GetKeyCode() == WXK_LEFT) {
2029 wxCommandEvent dummy;
2031 }
else if (e.CmdDown() && e.GetKeyCode() == WXK_RIGHT) {
2033 wxCommandEvent dummy;
2035 }
else if (e.GetKeyCode() ==
'f') {
2036 bool left = e.GetEventObject() ==
m_leftImg;
2042 }
else if (e.GetKeyCode() ==
'g') {
2044 long th = wxGetNumberFromUser(_(
"Create control points.\nTo create less points,\nenter a higher number."), _(
"Corner Detection threshold"), _(
"Create control points"), 400, 0, 32000);
2048 long scale = wxGetNumberFromUser(_(
"Create control points"), _(
"Corner Detection scale"), _(
"Create control points"), 2);
2055 DEBUG_DEBUG(
"corner threshold: " << th <<
" scale: " << scale);
2059 }
catch (std::exception & e) {
2060 wxLogError(_(
"Error during control point creation:\n") + wxString(e.what(), wxConvLocal));
2086 wxLIST_STATE_SELECTED);
2136 wxCommandEvent tmpEvt;
2137 tmpEvt.SetInt(XRCCTRL(*
this,
"cp_editor_choice_zoom",wxChoice)->GetSelection());
2157 MainFrame::Get()->SetStatusText(_(
"Select point in right image"),0);
2169 MainFrame::Get()->SetStatusText(_(
"Select point in left image"),0);
2201 }
else if (left >= nImgs) {
2207 }
else if (right >= nImgs) {
2222 }
else if (left >= nImgs) {
2228 }
else if (right >= nImgs) {
2275 linefindSetting.
SetProg(wxT(
"linefind.exe"));
2277 linefindSetting.
SetProg(wxT(
"linefind"));
2279 linefindSetting.
SetArgs(wxT(
"-o %o %s"));
2297 wxMessageBox(_(
"Cannot run celeste without at least one control point connecting the two images"),_(
"Error"));
2298 std::cout <<
"Cannot run celeste without at least one control point connecting the two images" << std::endl;
2312 wxConfigBase *cfg = wxConfigBase::Get();
2319 int radius=(t)?10:20;
2328 vigra::UInt16RGBImage in;
2329 if(img->image16->width()>0)
2331 in.resize(img->image16->size());
2337 in.resize(im8->size());
2341 if (!img->iccProfile->empty())
2356 if(!cloudCP.empty())
2364 wxMessageBox(wxString::Format(_(
"Removed %lu control points"), static_cast<unsigned long int>(cloudCP.size())), _(
"Celeste result"), wxOK | wxICON_INFORMATION,
this);
2383 double x = it->second.error;
2384 double delta = x - mean;
2386 var += delta*(x - mean);
2388 var = var / (n - 1);
2389 const double limit = (sqrt(var) > mean) ? mean : (mean + sqrt(var));
2393 if (it->second.error > limit)
2395 removedCPs.insert(it->first);
2398 if (!removedCPs.empty())
2400 wxMessageBox(wxString::Format(_(
"Removed %lu control points"), (
unsigned long int)removedCPs.size()), _(
"Cleaning"), wxOK | wxICON_INFORMATION,
this);
2412 wxString s(_(
"Create cp"));
2413 s.Append(wxT(
"\u25bc"));
2415 m_actionButton->SetToolTip(_(
"Create control points for image pair with currently selected control point detector on photos tab."));
2417 wxConfig::Get()->Write(wxT(
"/CPEditorPanel/ActionMode"), static_cast<long>(
m_cpActionButtonMode));
2423 wxString s(_(
"Celeste"));
2424 s.Append(wxT(
"\u25bc"));
2426 m_actionButton->SetToolTip(_(
"Tries to remove control points from clouds"));
2428 wxConfig::Get()->Write(wxT(
"/CPEditorPanel/ActionMode"), static_cast<long>(
m_cpActionButtonMode));
2434 wxString s(_(
"Clean cp"));
2435 s.Append(wxT(
"\u25bc"));
2437 m_actionButton->SetToolTip(_(
"Remove outlying control points by statistical method"));
2439 wxConfig::Get()->Write(wxT(
"/CPEditorPanel/ActionMode"), static_cast<long>(
m_cpActionButtonMode));
2443 const vigra::Diff2D & srcPnt,
2445 unsigned int moveNr,
2451 if (!
PointFineTune(srcNr, srcPnt, templWidth, moveNr, movePnt, sWidth, result))
2471 unsigned int srcNr = cp.image1Nr;
2472 unsigned int moveNr = cp.image2Nr;
2476 srcNr = cp.image2Nr;
2477 moveNr = cp.image1Nr;
2485 if (result.
x < 0 || result.
y < 0)
2494 cp.x2 = movedSrcPnt.
x;
2495 cp.y2 = movedSrcPnt.
y;
2499 cp.x1 = movedSrcPnt.
x;
2500 cp.y1 = movedSrcPnt.
y;
2526 vigra::Diff2D srcPnt(leftP.
toDiff2D());
2528 vigra::Diff2D movePnt(rightP.
toDiff2D());
2539 if (result.
x < 0 || result.
y < 0)
2560 size_t nrNormalCp = 0;
2570 DEBUG_WARN(
"Cannot estimate position without at least one point");
2577 leftImg.setPitch(0);
2584 rightImg.setPitch(0);
2585 rightImg.setRoll(0);
2595 std::set<std::string> opt;
2596 optVec.push_back(opt);
2603 optVec.push_back(opt);
2633 if (t.
x < 0) t.
x = 0;
2634 if (t.
y < 0) t.
y = 0;
2647 int colNum = e.GetColumn();
2648 wxConfigBase::Get()->Write( wxString::Format(wxT(
"/CPEditorPanel/ColumnWidth%d"),colNum),
m_cpList->GetColumnWidth(colNum) );
2653 const int newCol = e.GetColumn();
2679 while (roll > 360) roll-= 360;
2680 while (roll < 0) roll += 360;
2682 while (pitch > 180) pitch -= 360;
2683 while (pitch < -180) pitch += 360;
2684 bool headOver = (pitch > 90 || pitch < -90);
2686 if (wxConfig::Get()->Read(wxT(
"/CPEditorPanel/AutoRot"),1L)) {
2687 if (roll >= 315 || roll < 45) {
2689 }
else if (roll >= 45 && roll < 135) {
2691 }
else if (roll >= 135 && roll < 225) {
2703 : wxXmlResourceHandler()
2712 cp->Create(m_parentAsWindow,
2714 GetPosition(), GetSize(),
2715 GetStyle(wxT(
"style")),
2725 return IsOfClass(node, wxT(
"CPEditorPanel"));
void CalcCPDistance(HuginBase::Panorama *pano)
Get maximum CP distance for all images pairs containing the reference image.
PanoramaOptions::ProjectionFormat getProjection() const
void ScrollDelta(const wxPoint &delta)
scroll the window by delta pixels
void OnColumnHeaderClick(wxListEvent &e)
Dummy progress display, without output.
void SelectGlobalPoint(unsigned int globalNr)
Select a point.
void NewPointChange(hugin_utils::FDiff2D p, bool left)
static double calcOptimalPanoScale(const SrcPanoImage &src, const PanoramaOptions &dest)
function to calculate the scaling factor so that the distances in the input image and panorama image ...
HuginBase::PTools::Transform m_leftInvTransformMag
void setHeight(unsigned int h)
set panorama height
bool updateDisplayValue(const wxString &message, const wxString &filename=wxEmptyString)
virtual wxObject * DoCreateResource()
void setNewPoint(const hugin_utils::FDiff2D &p)
set new point to a specific point
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
CPEventMode getMode()
accessor functions (they could check mode to see if a getXYZ() is allowed
#define HUGIN_FT_LOCAL_SEARCH_WIDTH
vigra_ext::CorrelationResult PointFineTuneProjectionAware(const HuginBase::SrcPanoImage &templ, const vigra::UInt8RGBImage &templImg, vigra::Diff2D templPos, int templSize, const HuginBase::SrcPanoImage &search, const vigra::UInt8RGBImage &searchImg, vigra::Diff2D searchPos, int sWidth)
function for fine-tune with remapping to stereographic projection
#define HUGIN_FT_SEARCH_AREA_PERCENT
bool str2double(const wxString &s, double &d)
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
void deselect()
remove selection.
wxMenu * m_cpActionContextMenu
CPImagesComboBox * m_leftChoice
void SortList()
sorting functions
control point editor panel.
bool PointFineTune(unsigned int tmplImgNr, const vigra::Diff2D &tmplPoint, int tmplWidth, unsigned int subjImgNr, const hugin_utils::FDiff2D &subjPoint, int searchWidth, vigra_ext::CorrelationResult &tunedPos)
search for region in destImg
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
void OnCPListDeselect(wxListEvent &e)
CPImagesComboBox * m_rightChoice
virtual bool CanHandle(wxXmlNode *node)
hugin_utils::FDiff2D corrPos
CorrelationResult PointFineTune(const IMAGET &templImg, ACCESSORT access_t, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, ACCESSORS access_s, vigra::Diff2D searchPos, int sWidth)
fine tune a point with normalized cross correlation
void OnAddButton(wxCommandEvent &e)
void OnCreateCPButton(wxCommandEvent &e)
#define HUGIN_FT_CURV_THRESHOLD
void registerPTWXDlgFcn()
void OnCPListSelect(wxListEvent &e)
#define HUGIN_FT_ROTATION_STEPS
CPTabActionButtonMode m_cpActionButtonMode
void selectPoint(unsigned int, bool scrollTo=true)
select a point for usage
Events to notify about new point / region / point change.
void FineTuneSelectedPoint(bool left)
int wxCALLBACK SortIndexAscending(wxIntPtr item1, wxIntPtr item2, wxIntPtr WXUNUSED(sortData))
void OnKey(wxKeyEvent &e)
void deregisterPTWXDlgFcn()
int getNextCPTypeLineNumber() const
get the number of a control point
general : Matrix3 is a class for handling 3x3 Matrix manipulation.
std::size_t getNrOfCtrlPoints() const
number of control points
bool set_contains(const _Container &c, const typename _Container::key_type &key)
#define SORTASCENDING(functionName, var)
#define DEBUG_ASSERT(cond)
HuginBase::ImageCache::ImageCacheRGB8Ptr ImageCacheRGB8Ptr
void SetArgs(wxString new_args)
sets arguments of one step detector or feature descriptor
void OnFineTuneButton(wxCommandEvent &e)
include file for the hugin project
void setLeftImage(unsigned int imgNr)
set left image
void GetRotationPT(double &Yaw, double &Pitch, double &Roll)
GetRotation in panotools style.
Owner Drawn ComboBox for showing connected images on CP tab.
const CPVector & getCtrlPoints() const
get all control point of this Panorama
int getHeight() const
Get the height of the image in pixels.
void EnablePointEdit(bool state)
enable or disable controls for editing other points
void OnNextImg(wxCommandEvent &e)
unsigned int getPointNr()
remove several control points
represents a control point
const Map::mapped_type & const_map_get(const Map &m, const typename Map::key_type &key)
void SetRotationPT(double yaw, double pitch, double roll)
set rotation in panotools style, code adapted from Panotools-Script by Bruno Postle ...
void ShowControlPoint(unsigned int cpNr)
show a control point
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
CorrelationResult PointFineTuneRotSearch(const IMAGET &templImg, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, vigra::Diff2D searchPos, int sWidth, double startAngle, double stopAngle, int angleSteps)
fine tune a point with normalized cross correlation, searches x,y and phi (rotation around z) ...
void OnActionContextMenu(wxContextMenuEvent &e)
virtual ~CPEditorPanel()
dtor.
void OnActionButton(wxCommandEvent &e)
unsigned int m_leftImageNr
std::set< unsigned int > UIntSet
void OnCleanCPButton(wxCommandEvent &e)
void OnTextPointChange(wxCommandEvent &e)
void clearNewPoint()
clear new point
wxCheckBox * m_fineTuneCB
double getScale()
return scale factor, 0 for autoscale
right point, finetune for left point failed
void OnLeftChoiceChange(wxCommandEvent &e)
#define HUGIN_FT_TEMPLATE_SIZE
class, which stores all settings of one cp detector
void CreateNewPoint()
this is used to finally create the point in the panorama model
wxCheckBox * m_showLinesCB
const VariableMap getImageVariables(unsigned int imgNr) const
Get the variables of an image.
void OnZoom(wxCommandEvent &e)
std::size_t getNrOfImages() const
number of images.
static MainFrame * Get()
hack.. kind of a pseudo singleton...
void Init(CPEditorPanel *parent)
void clearCtrlPointList()
clear internal control point list
CPCreationState
the state machine for point selection: it is set to the current selection
void FineTuneNewPoint(bool left)
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be 'add' method?)
void SetProg(wxString new_prog)
sets program for one step detector or feature descriptor
#define HUGIN_CELESTE_FILTER
int getWidth() const
Get the width of the image in pixels.
CPImageCtrl::ImageRotation GetRot(double yaw, double roll, double pitch)
calculate rotation required for upright image display from roll, pitch and yaw angles ...
const ControlPoint & getCtrlPoint(std::size_t nr) const
get a control point, counting starts with 0
hugin_utils::FDiff2D EstimatePoint(const hugin_utils::FDiff2D &p, bool left)
Estimate position of point in the other image.
#define HUGIN_CELESTE_THRESHOLD
HuginBase::PTools::Transform m_rightTransform
void showTemplateArea(bool show=true)
wxPoint MaxScrollDelta(wxPoint delta)
calculate maximum delta that is allowed when scrolling
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
Maximum of correlation, position and value.
void OnDeleteButton(wxCommandEvent &e)
hugin_utils::FDiff2D curv
bool globalPNr2LocalPNr(unsigned int &localNr, unsigned int globalNr) const
map a global point nr to a local one, if possible
#define SORTDESCENDING(functionName, var)
CPCreationState cpCreationState
wxwindows specific panorama commands
evaluate x, points are on a vertical line
unsigned int localPNr2GlobalPNr(unsigned int localNr) const
find a local point
void OnActionSelectCleanCP(wxCommandEvent &e)
static GlobalCmdHist & getInstance()
void OnActionSelectCeleste(wxCommandEvent &e)
point in left image selected
void OnShowLinesCheckbox(wxCommandEvent &e)
std::set< unsigned int > mirroredPoints
void update()
initiate redraw
TDiff2D< double > FDiff2D
const hugin_utils::FDiff2D & getPoint()
CPImageCtrl::ImageRotation m_rightRot
HuginBase::PTools::Transform m_leftTransformMag
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
void ClearSelection()
unselect a point
HuginBase::PTools::Transform m_leftInvTransform
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
void setTransforms(HuginBase::PTools::Transform *firstTrans, HuginBase::PTools::Transform *firstInvTrans, HuginBase::PTools::Transform *secondInvTrans)
!! from PTOptimise.h 1951
HuginBase::PTools::Transform m_rightInvTransform
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
void showSearchArea(bool show=true)
show/hide the search area rectangle
CPImageCtrl::ImageRotation m_leftRot
void RunCPGenerator(CPDetectorSetting &setting, const HuginBase::UIntSet &img)
run the cp generator with the given setting on selected images
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.
wxButton * m_actionButton
unsigned int m_rightImageNr
void Init(HuginBase::Panorama *pano)
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
int wxCALLBACK SortIndexDescending(wxIntPtr item1, wxIntPtr item2, wxIntPtr WXUNUSED(sortData))
void addObserver(PanoramaObserver *o)
add a panorama observer.
void estimateAndAddOtherPoint(const hugin_utils::FDiff2D &p, bool left, CPImageCtrl *thisImg, unsigned int thisImgNr, CPCreationState THIS_POINT, CPCreationState THIS_POINT_RETRY, CPImageCtrl *otherImg, unsigned int otherImgNr, CPCreationState OTHER_POINT, CPCreationState OTHER_POINT_RETRY)
estimate and set point in other image
struct celeste::svm_model * GetSVMModel()
unsigned int getWidth() const
hugin_utils::FDiff2D getNewPoint()
get the new point
void OnCPEvent(CPEvent &ev)
void changeState(CPCreationState newState)
#define HUGIN_FT_ROTATION_START_ANGLE
include file for the hugin project
void UpdateTransforms()
updated the internal transform object for drawing line in controls
void OnPrevImg(wxCommandEvent &e)
const PanoramaOptions & getOptions() const
returns the options for this panorama
void OnRightChoiceChange(wxCommandEvent &e)
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
void SelectLocalPoint(unsigned int LVpointNr, bool scrollLeft=true, bool scrollRight=true)
select a local point.
HuginBase::UIntSet getCelesteControlPoints(struct svm_model *model, vigra::UInt16RGBImage &input, HuginBase::CPointVector cps, int radius, float threshold, int resize_dimension, bool verbose)
HuginBase::Panorama * m_pano
void setRightImage(unsigned int imgNr)
set right image
#define HUGIN_FT_CORR_THRESHOLD
CPScrollHint m_scrollHint
void panoramaChanged(HuginBase::Panorama &pano)
called when the panorama changes and we should update our display
void OnActionSelectCreate(wxCommandEvent &e)
void OnColumnWidthChange(wxListEvent &e)
void setCtrlPoint(const HuginBase::ControlPoint &cp, const bool mirrored)
add control piont to internal cp list
HuginBase::PTools::Transform m_rightInvTransformMag
void setSize(vigra::Size2D val)
Set the image size in pixels.
void setScale(double factor)
set the scaling factor for cp display.
hugin_utils::FDiff2D maxpos
std::vector< ControlPoint > CPVector
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
void transformImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
const float getVerticalCPBias()
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
std::vector< std::set< std::string > > OptimizeVector
const HuginBase::ControlPoint & getControlPoint()
vigra::Diff2D toDiff2D() const
void setImage(const std::string &filename, ImageRotation rot)
display img.
bool updateDisplay(const wxString &message)
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
bool m_listenToPageChange
HuginBase::PTools::Transform m_rightTransformMag
void setMagTransforms(HuginBase::PTools::Transform *magTrans, HuginBase::PTools::Transform *magInvTrans)
void showPosition(hugin_utils::FDiff2D point, bool warpPointer=false)
Show point x, y.
ProjectionFormat
Projection of final panorama.
wxCheckBox * m_estimateCB
selected point in right image
wxChoice * m_cpModeChoice
void setSameImage(bool sameImage)
point in left image selected, finetune failed in right image
hugin_utils::FDiff2D LocalFineTunePoint(unsigned int srcNr, const vigra::Diff2D &srcPnt, hugin_utils::FDiff2D &movedSrcPnt, unsigned int moveNr, const hugin_utils::FDiff2D &movePnt)
HuginBase::PTools::Transform m_leftTransform
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxT("panel"))
All variables of a source image.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
HuginBase::CPointVector currentPoints
bool IsShowingCorrelation() const
vigra::Size2D getSize() const
get size of output image
#define HUGIN_FT_ROTATION_STOP_ANGLE
evaluate y, points are on a horizontal line
functions to handle icc profiles in images
left and right point selected, waiting for add point.
double m_detailZoomFactor
void OnCelesteButton(wxCommandEvent &e)
ImageRotation
image rotation.
#define HUGIN_FT_ROTATION_SEARCH
HuginBase::SrcPanoImage GetImageRotatedTo(const HuginBase::SrcPanoImage &img, const vigra::Diff2D &point, int testWidth, double &neededHFOV)
void mirror()
swap (image1Nr,x1,y1) with (image2Nr,x2,y2)
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
notifies about changes to images
unsigned int m_selectedPoint
void ApplyICCProfile(ImageType &image, const vigra::ImageImportInfo::ICCProfile &iccProfile, const cmsUInt32Number imageFormat)
converts given image with iccProfile to sRGB/gray space, need to give pixel type in lcms2 format work...
void SetRefImage(HuginBase::Panorama *pano, unsigned int newRefImg)
Set new reference image.
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
void UpdateDisplay(bool newImages)
updates the display after another image has been selected.
void ShowLines(bool isShown)