00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "find_object/Settings.h"
00029
00030 #include "ParametersToolBox.h"
00031 #include <QtGui/QComboBox>
00032 #include <QtGui/QDoubleSpinBox>
00033 #include <QtGui/QLineEdit>
00034 #include <QtGui/QLabel>
00035 #include <QtGui/QGroupBox>
00036 #include <QtGui/QCheckBox>
00037 #include <QtGui/QVBoxLayout>
00038 #include <QtGui/QMessageBox>
00039 #include <stdio.h>
00040 #include "find_object/utilite/ULogger.h"
00041
00042 namespace find_object {
00043
00044 ParametersToolBox::ParametersToolBox(QWidget *parent) :
00045 QToolBox(parent)
00046 {
00047 }
00048
00049 ParametersToolBox::~ParametersToolBox()
00050 {
00051 }
00052
00053 QWidget * ParametersToolBox::getParameterWidget(const QString & key)
00054 {
00055 return this->findChild<QWidget*>(key);
00056 }
00057
00058 QStringList ParametersToolBox::resetPage(int index)
00059 {
00060 QStringList paramChanged;
00061 const QObjectList & children = this->widget(index)->children();
00062 for(int j=0; j<children.size();++j)
00063 {
00064 QString key = children.at(j)->objectName();
00065
00066 if(key.compare(Settings::kGeneral_nextObjID()) != 0)
00067 {
00068 QVariant value = Settings::getDefaultParameters().value(key, QVariant());
00069 if(value.isValid())
00070 {
00071 Settings::setParameter(key, value);
00072
00073 if(qobject_cast<QComboBox*>(children.at(j)))
00074 {
00075 if(((QComboBox*)children.at(j))->currentIndex() != value.toString().split(':').first().toInt())
00076 {
00077 ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt());
00078 paramChanged.append(key);
00079 }
00080 }
00081 else if(qobject_cast<QSpinBox*>(children.at(j)))
00082 {
00083 if(((QSpinBox*)children.at(j))->value() != value.toInt())
00084 {
00085 ((QSpinBox*)children.at(j))->setValue(value.toInt());
00086 paramChanged.append(key);
00087 }
00088 }
00089 else if(qobject_cast<QDoubleSpinBox*>(children.at(j)))
00090 {
00091 if(((QDoubleSpinBox*)children.at(j))->value() != value.toDouble())
00092 {
00093 ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble());
00094 paramChanged.append(key);
00095 }
00096 }
00097 else if(qobject_cast<QCheckBox*>(children.at(j)))
00098 {
00099 if(((QCheckBox*)children.at(j))->isChecked() != value.toBool())
00100 {
00101 ((QCheckBox*)children.at(j))->setChecked(value.toBool());
00102 paramChanged.append(key);
00103 }
00104 }
00105 else if(qobject_cast<QLineEdit*>(children.at(j)))
00106 {
00107 if(((QLineEdit*)children.at(j))->text().compare(value.toString()) != 0)
00108 {
00109 ((QLineEdit*)children.at(j))->setText(value.toString());
00110 paramChanged.append(key);
00111 }
00112 }
00113 }
00114 }
00115 }
00116 return paramChanged;
00117 }
00118
00119 void ParametersToolBox::resetCurrentPage()
00120 {
00121 this->blockSignals(true);
00122 QStringList paramChanged = this->resetPage(this->currentIndex());
00123 this->blockSignals(false);
00124 Q_EMIT parametersChanged(paramChanged);
00125 }
00126
00127 void ParametersToolBox::resetAllPages()
00128 {
00129 QStringList paramChanged;
00130 this->blockSignals(true);
00131 for(int i=0; i< this->count(); ++i)
00132 {
00133 paramChanged.append(this->resetPage(i));
00134 }
00135 this->blockSignals(false);
00136 Q_EMIT parametersChanged(paramChanged);
00137 }
00138
00139 void ParametersToolBox::updateParametersVisibility()
00140 {
00141
00142 QComboBox * descriptorBox = this->findChild<QComboBox*>(Settings::kFeature2D_2Descriptor());
00143 QComboBox * detectorBox = this->findChild<QComboBox*>(Settings::kFeature2D_1Detector());
00144 if(descriptorBox && detectorBox)
00145 {
00146 QString group = Settings::kFeature2D_2Descriptor().split('/').first();
00147 QWidget * panel = 0;
00148 for(int i=0; i<this->count(); ++i)
00149 {
00150 if(this->widget(i)->objectName().compare(group) == 0)
00151 {
00152 panel = this->widget(i);
00153 break;
00154 }
00155 }
00156 if(panel)
00157 {
00158 const QObjectList & objects = panel->children();
00159 QString descriptorName = descriptorBox->currentText();
00160 QString detectorName = detectorBox->currentText();
00161
00162 for(int i=0; i<objects.size(); ++i)
00163 {
00164 if(!objects[i]->objectName().isEmpty())
00165 {
00166 if(objects[i]->objectName().contains(descriptorName) || objects[i]->objectName().contains(detectorName))
00167 {
00168 ((QWidget*)objects[i])->setVisible(true);
00169 }
00170 else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
00171 {
00172 ((QWidget*)objects[i])->setVisible(false);
00173 }
00174 }
00175 }
00176 }
00177 }
00178
00179 QComboBox * nnBox = this->findChild<QComboBox*>(Settings::kNearestNeighbor_1Strategy());
00180 if(nnBox)
00181 {
00182 QString group = Settings::kNearestNeighbor_1Strategy().split('/').first();
00183 QWidget * panel = 0;
00184 for(int i=0; i<this->count(); ++i)
00185 {
00186 if(this->widget(i)->objectName().compare(group) == 0)
00187 {
00188 panel = this->widget(i);
00189 break;
00190 }
00191 }
00192 if(panel)
00193 {
00194 const QObjectList & objects = panel->children();
00195 QString nnName = nnBox->currentText();
00196
00197 for(int i=0; i<objects.size(); ++i)
00198 {
00199 if(!objects[i]->objectName().isEmpty())
00200 {
00201 if(objects[i]->objectName().contains(nnName))
00202 {
00203 ((QWidget*)objects[i])->setVisible(true);
00204 }
00205 else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
00206 {
00207 ((QWidget*)objects[i])->setVisible(false);
00208 if(nnBox->currentIndex() < 6 && objects[i]->objectName().split('/').at(1).contains("search"))
00209 {
00210
00211 ((QWidget*)objects[i])->setVisible(true);
00212 }
00213 }
00214 else if(objects[i]->objectName().split('/').at(1).contains("Distance_type"))
00215 {
00216
00217 ((QWidget*)objects[i])->setVisible(nnBox->currentIndex() != 6);
00218 }
00219 }
00220 }
00221 }
00222 }
00223 }
00224
00225 void ParametersToolBox::setupUi()
00226 {
00227 this->removeItem(0);
00228 QWidget * currentItem = 0;
00229 const ParametersMap & parameters = Settings::getParameters();
00230 for(ParametersMap::const_iterator iter=parameters.constBegin();
00231 iter!=parameters.constEnd();
00232 ++iter)
00233 {
00234 QStringList splitted = iter.key().split('/');
00235 QString group = splitted.first();
00236 QString name = splitted.last();
00237 if(currentItem == 0 || currentItem->objectName().compare(group) != 0)
00238 {
00239 currentItem = new QWidget(this);
00240 this->addItem(currentItem, group);
00241 currentItem->setObjectName(group);
00242 QVBoxLayout * layout = new QVBoxLayout(currentItem);
00243 currentItem->setLayout(layout);
00244 layout->setContentsMargins(0,0,0,0);
00245 layout->setSpacing(0);
00246 layout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding));
00247
00248 addParameter(layout, iter.key(), iter.value());
00249 }
00250 else
00251 {
00252 addParameter((QVBoxLayout*)currentItem->layout(), iter.key(), iter.value());
00253 }
00254 }
00255
00256 updateParametersVisibility();
00257 }
00258
00259 void ParametersToolBox::updateParameter(const QString & key)
00260 {
00261 QWidget * widget = this->findChild<QWidget*>(key);
00262 QString type = Settings::getParametersType().value(key);
00263 if(type.compare("QString") == 0)
00264 {
00265 QString value = Settings::getParameter(key).toString();
00266 if(value.contains(';'))
00267 {
00268
00269 QStringList splitted = value.split(':');
00270 ((QComboBox*)widget)->setCurrentIndex(splitted.first().toInt());
00271 }
00272 else
00273 {
00274 ((QLineEdit*)widget)->setText(value);
00275 }
00276 }
00277 else if(type.compare("int") == 0)
00278 {
00279 ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt());
00280 }
00281 else if(type.compare("uint") == 0)
00282 {
00283 ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt());
00284 }
00285 else if(type.compare("double") == 0)
00286 {
00287 ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble());
00288 }
00289 else if(type.compare("float") == 0)
00290 {
00291 ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble());
00292 }
00293 else if(type.compare("bool") == 0)
00294 {
00295 ((QCheckBox*)widget)->setChecked(Settings::getParameter(key).toBool());
00296 }
00297 }
00298
00299 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00300 const QString & key,
00301 const QVariant & value)
00302 {
00303 QString type = Settings::getParametersType().value(key);
00304 if(type.compare("QString") == 0)
00305 {
00306 addParameter(layout, key, value.toString());
00307 }
00308 else if(type.compare("int") == 0)
00309 {
00310 addParameter(layout, key, value.toInt());
00311 }
00312 else if(type.compare("uint") == 0)
00313 {
00314 addParameter(layout, key, value.toInt());
00315 }
00316 else if(type.compare("double") == 0)
00317 {
00318 addParameter(layout, key, value.toDouble());
00319 }
00320 else if(type.compare("float") == 0)
00321 {
00322 addParameter(layout, key, value.toDouble());
00323 }
00324 else if(type.compare("bool") == 0)
00325 {
00326 addParameter(layout, key, value.toBool());
00327 }
00328 }
00329
00330 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00331 const QString & key,
00332 const QString & value)
00333 {
00334 if(value.contains(';'))
00335 {
00336 QComboBox * widget = new QComboBox(this);
00337 widget->setObjectName(key);
00338 QStringList splitted = value.split(':');
00339 widget->addItems(splitted.last().split(';'));
00340 #if FINDOBJECT_NONFREE == 0
00341 if(key.compare(Settings::kFeature2D_1Detector()) == 0)
00342 {
00343 widget->setItemData(5, 0, Qt::UserRole - 1);
00344 widget->setItemData(7, 0, Qt::UserRole - 1);
00345 }
00346 if(key.compare(Settings::kFeature2D_2Descriptor()) == 0)
00347 {
00348 widget->setItemData(2, 0, Qt::UserRole - 1);
00349 widget->setItemData(3, 0, Qt::UserRole - 1);
00350 }
00351 if(key.compare(Settings::kNearestNeighbor_1Strategy()) == 0)
00352 {
00353
00354 widget->setItemData(0, 0, Qt::UserRole - 1);
00355 widget->setItemData(1, 0, Qt::UserRole - 1);
00356 widget->setItemData(2, 0, Qt::UserRole - 1);
00357 widget->setItemData(3, 0, Qt::UserRole - 1);
00358 widget->setItemData(4, 0, Qt::UserRole - 1);
00359 }
00360 #endif
00361 widget->setCurrentIndex(splitted.first().toInt());
00362 connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int)));
00363 addParameter(layout, key, widget);
00364 }
00365 else
00366 {
00367 QLineEdit * widget = new QLineEdit(value, this);
00368 widget->setObjectName(key);
00369 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00370 addParameter(layout, key, widget);
00371 }
00372 }
00373
00374 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00375 const QString & key,
00376 const double & value)
00377 {
00378 QDoubleSpinBox * widget = new QDoubleSpinBox(this);
00379 double def = Settings::getDefaultParameters().value(key).toDouble();
00380 if(def<0.001)
00381 {
00382 widget->setDecimals(4);
00383 }
00384 else if(def<0.01)
00385 {
00386 widget->setDecimals(3);
00387 }
00388
00389 if(def>=0.0)
00390 {
00391 widget->setMaximum(def*1000000.0);
00392 }
00393 else if(def==0.0)
00394 {
00395 widget->setMaximum(1000000.0);
00396 }
00397 else if(def<0.0)
00398 {
00399 widget->setMinimum(def*1000000.0);
00400 widget->setMaximum(0.0);
00401 }
00402 widget->setValue(value);
00403 widget->setObjectName(key);
00404 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00405 addParameter(layout, key, widget);
00406 }
00407
00408 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00409 const QString & key,
00410 const int & value)
00411 {
00412 QSpinBox * widget = new QSpinBox(this);
00413 int def = Settings::getDefaultParameters().value(key).toInt();
00414
00415 if(def>0)
00416 {
00417 widget->setMaximum(def*1000000);
00418 }
00419 else if(def == 0)
00420 {
00421 widget->setMaximum(1000000);
00422 }
00423 else if(def<0)
00424 {
00425 widget->setMinimum(def*1000000);
00426 widget->setMaximum(0);
00427 }
00428 widget->setValue(value);
00429 widget->setObjectName(key);
00430 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00431 addParameter(layout, key, widget);
00432 }
00433
00434 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00435 const QString & key,
00436 const bool & value)
00437 {
00438 QCheckBox * widget = new QCheckBox(this);
00439 widget->setChecked(value);
00440 widget->setObjectName(key);
00441 connect(widget, SIGNAL(stateChanged(int)), this, SLOT(changeParameter(int)));
00442 addParameter(layout, key, widget);
00443 }
00444
00445 void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, QWidget * widget)
00446 {
00447 QHBoxLayout * hLayout = new QHBoxLayout();
00448 layout->insertLayout(layout->count()-1, hLayout);
00449 QString tmp = key.split('/').last();
00450 if(tmp.at(0).isDigit())
00451 {
00452 tmp.remove(0,1);
00453 }
00454 QLabel * label = new QLabel(tmp, this);
00455 label->setObjectName(key+"/label");
00456 label->setToolTip(QString("<FONT>%1</FONT>").arg(Settings::getDescriptions().value(key, "")));
00457 label->setTextInteractionFlags(Qt::TextSelectableByMouse);
00458 hLayout->addWidget(label);
00459 hLayout->addWidget(widget);
00460 }
00461
00462 void ParametersToolBox::changeParameter(const QString & value)
00463 {
00464 if(sender())
00465 {
00466 Settings::setParameter(sender()->objectName(), value);
00467 QStringList paramChanged;
00468 paramChanged.append(sender()->objectName());
00469 Q_EMIT parametersChanged(paramChanged);
00470 }
00471 }
00472 void ParametersToolBox::changeParameter()
00473 {
00474 if(sender())
00475 {
00476 QDoubleSpinBox * doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
00477 QSpinBox * spinBox = qobject_cast<QSpinBox*>(sender());
00478 QLineEdit * lineEdit = qobject_cast<QLineEdit*>(sender());
00479 if(doubleSpinBox)
00480 {
00481 Settings::setParameter(sender()->objectName(), doubleSpinBox->value());
00482 }
00483 else if(spinBox)
00484 {
00485 if(spinBox->objectName().compare(Settings::kHomography_minimumInliers()) == 0 &&
00486 spinBox->value() < 4)
00487 {
00488 Settings::setHomography_minimumInliers(4);
00489 spinBox->blockSignals(true);
00490 this->updateParameter(Settings::kHomography_minimumInliers());
00491 spinBox->blockSignals(false);
00492 }
00493 else
00494 {
00495 Settings::setParameter(sender()->objectName(), spinBox->value());
00496 }
00497 }
00498 else if(lineEdit)
00499 {
00500 Settings::setParameter(sender()->objectName(), lineEdit->text());
00501 }
00502 QStringList paramChanged;
00503 paramChanged.append(sender()->objectName());
00504 Q_EMIT parametersChanged(paramChanged);
00505 }
00506 }
00507
00508 void ParametersToolBox::changeParameter(const int & value)
00509 {
00510 if(sender())
00511 {
00512 QStringList paramChanged;
00513 QComboBox * comboBox = qobject_cast<QComboBox*>(sender());
00514 QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender());
00515 if(comboBox)
00516 {
00517 bool nnStrategyChanged = false;
00518
00519 if(comboBox->objectName().compare(Settings::kFeature2D_2Descriptor()) == 0 ||
00520 comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0)
00521 {
00522 QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
00523 QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
00524 QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
00525 bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 ||
00526 descriptorBox->currentText().compare("Brief") == 0 ||
00527 descriptorBox->currentText().compare("BRISK") == 0 ||
00528 descriptorBox->currentText().compare("FREAK") == 0;
00529 if(isBinaryDescriptor && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0)
00530 {
00531 QMessageBox::warning(this,
00532 tr("Warning"),
00533 tr("Current selected descriptor type (\"%1\") is binary while nearest neighbor strategy is not (\"%2\").\n"
00534 "Falling back to \"BruteForce\" nearest neighbor strategy with Hamming distance (by default).")
00535 .arg(descriptorBox->currentText())
00536 .arg(nnBox->currentText()));
00537 QString tmp = Settings::getNearestNeighbor_1Strategy();
00538 *tmp.begin() = '6';
00539 Settings::setNearestNeighbor_1Strategy(tmp);
00540 tmp = Settings::getNearestNeighbor_2Distance_type();
00541 *tmp.begin() = '8';
00542 Settings::setNearestNeighbor_2Distance_type(tmp);
00543 nnBox->blockSignals(true);
00544 distBox->blockSignals(true);
00545 this->updateParameter(Settings::kNearestNeighbor_1Strategy());
00546 this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
00547 nnBox->blockSignals(false);
00548 distBox->blockSignals(false);
00549 if(sender() == nnBox)
00550 {
00551 this->updateParametersVisibility();
00552 return;
00553 }
00554 nnStrategyChanged = true;
00555 paramChanged.append(Settings::kNearestNeighbor_1Strategy());
00556 paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
00557 }
00558 else if(!isBinaryDescriptor && nnBox->currentText().compare("Lsh") == 0)
00559 {
00560 QMessageBox::warning(this,
00561 tr("Warning"),
00562 tr("Current selected descriptor type (\"%1\") is not binary while nearest neighbor strategy is (\"%2\").\n"
00563 "Falling back to \"KDTree\" nearest neighbor strategy with Euclidean_L2 distance (by default).")
00564 .arg(descriptorBox->currentText())
00565 .arg(nnBox->currentText()));
00566 QString tmp = Settings::getNearestNeighbor_1Strategy();
00567 *tmp.begin() = '1';
00568 Settings::setNearestNeighbor_1Strategy(tmp);
00569 tmp = Settings::getNearestNeighbor_2Distance_type();
00570 *tmp.begin() = '0';
00571 Settings::setNearestNeighbor_2Distance_type(tmp);
00572 nnBox->blockSignals(true);
00573 distBox->blockSignals(true);
00574 this->updateParameter(Settings::kNearestNeighbor_1Strategy());
00575 this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
00576 nnBox->blockSignals(false);
00577 distBox->blockSignals(false);
00578 if(sender() == nnBox)
00579 {
00580 this->updateParametersVisibility();
00581 return;
00582 }
00583 nnStrategyChanged = true;
00584 paramChanged.append(Settings::kNearestNeighbor_1Strategy());
00585 paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
00586 }
00587 }
00588
00589
00590 if(nnStrategyChanged ||
00591 comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 ||
00592 comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0)
00593 {
00594 QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
00595 QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
00596 if(nnBox->currentText().compare("BruteForce") != 0 && nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1)
00597 {
00598 QMessageBox::warning(this,
00599 tr("Warning"),
00600 tr("Current selected nearest neighbor strategy type (\"%1\") cannot handle distance strategy (\"%2\").\n"
00601 "Falling back to \"EUCLIDEAN_L2\" distance strategy (by default).")
00602 .arg(nnBox->currentText())
00603 .arg(distBox->currentText()));
00604 QString tmp = Settings::getNearestNeighbor_2Distance_type();
00605 *tmp.begin() = '0';
00606 Settings::setNearestNeighbor_2Distance_type(tmp);
00607 distBox->blockSignals(true);
00608 this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
00609 distBox->blockSignals(false);
00610 if(sender() == distBox)
00611 {
00612 this->updateParametersVisibility();
00613 return;
00614 }
00615 paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
00616 }
00617 }
00618
00619 QStringList items;
00620 for(int i=0; i<comboBox->count(); ++i)
00621 {
00622 items.append(comboBox->itemText(i));
00623 }
00624 QString merged = QString::number(value) + QString(":") + items.join(";");
00625 Settings::setParameter(sender()->objectName(), merged);
00626
00627 this->updateParametersVisibility();
00628 }
00629 else if(checkBox)
00630 {
00631 Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false);
00632 }
00633
00634 paramChanged.append(sender()->objectName());
00635 Q_EMIT parametersChanged(paramChanged);
00636 }
00637 }
00638
00639 }