mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 00:37:46 +08:00
Parameters: Added "Reg/VarianceNormalized". Registration: Transforms are now only normalized in Registration. Added rgbd_dataset tool. MainWindow: odom inliers-only shown option. ExportCloudsDialog: ignoring intermediate nodes for texturing (if they don't have data). DatabaseViewer: "optimized" checkbox enabled in Constraints view for non-neighbor links too.
This commit is contained in:
@@ -2206,6 +2206,10 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
}
|
||||
}
|
||||
progressDialog->incrementStep();
|
||||
if(i%100)
|
||||
{
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
UINFO("Iteration %d/%d: added %d loop closures.", n+1, iterations, (int)addedLinks.size()/2);
|
||||
progressDialog->appendText(tr("Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(iterations).arg(addedLinks.size()/2));
|
||||
@@ -3321,30 +3325,27 @@ void DatabaseViewer::updateConstraintView(
|
||||
.arg(sqrt(link.rotVariance()))
|
||||
.arg(sqrt(link.transVariance())));
|
||||
ui_->label_constraint->setText(QString("%1").arg(t.prettyPrint().c_str()).replace(" ", "\n"));
|
||||
if((link.type() == Link::kNeighbor || link.type() == Link::kNeighborMerged) &&
|
||||
graphes_.size() &&
|
||||
if(graphes_.size() &&
|
||||
(int)graphes_.size()-1 == ui_->horizontalSlider_iterations->maximum())
|
||||
{
|
||||
std::map<int, rtabmap::Transform> & graph = uValueAt(graphes_, ui_->horizontalSlider_iterations->value());
|
||||
if(link.type() == Link::kNeighbor || link.type() == Link::kNeighborMerged)
|
||||
{
|
||||
std::map<int, rtabmap::Transform>::iterator iterFrom = graph.find(link.from());
|
||||
std::map<int, rtabmap::Transform>::iterator iterTo = graph.find(link.to());
|
||||
if(iterFrom != graph.end() && iterTo != graph.end())
|
||||
{
|
||||
ui_->checkBox_showOptimized->setEnabled(true);
|
||||
Transform topt = iterFrom->second.inverse()*iterTo->second;
|
||||
float diff = topt.getDistance(t);
|
||||
Transform v1 = t.rotation()*Transform(1,0,0,0,0,0);
|
||||
Transform v2 = topt.rotation()*Transform(1,0,0,0,0,0);
|
||||
float a = pcl::getAngle3D(Eigen::Vector4f(v1.x(), v1.y(), v1.z(), 0), Eigen::Vector4f(v2.x(), v2.y(), v2.z(), 0));
|
||||
a = (a *180.0f) / CV_PI;
|
||||
ui_->label_constraint_opt->setText(QString("%1\n(error=%2% a=%3)").arg(QString(topt.prettyPrint().c_str()).replace(" ", "\n")).arg((diff/t.getNorm())*100.0f).arg(a));
|
||||
|
||||
if(ui_->checkBox_showOptimized->isChecked())
|
||||
{
|
||||
t = topt;
|
||||
}
|
||||
std::map<int, rtabmap::Transform>::iterator iterFrom = graph.find(link.from());
|
||||
std::map<int, rtabmap::Transform>::iterator iterTo = graph.find(link.to());
|
||||
if(iterFrom != graph.end() && iterTo != graph.end())
|
||||
{
|
||||
ui_->checkBox_showOptimized->setEnabled(true);
|
||||
Transform topt = iterFrom->second.inverse()*iterTo->second;
|
||||
float diff = topt.getDistance(t);
|
||||
Transform v1 = t.rotation()*Transform(1,0,0,0,0,0);
|
||||
Transform v2 = topt.rotation()*Transform(1,0,0,0,0,0);
|
||||
float a = pcl::getAngle3D(Eigen::Vector4f(v1.x(), v1.y(), v1.z(), 0), Eigen::Vector4f(v2.x(), v2.y(), v2.z(), 0));
|
||||
a = (a *180.0f) / CV_PI;
|
||||
ui_->label_constraint_opt->setText(QString("%1\n(error=%2% a=%3)").arg(QString(topt.prettyPrint().c_str()).replace(" ", "\n")).arg((diff/t.getNorm())*100.0f).arg(a));
|
||||
|
||||
if(ui_->checkBox_showOptimized->isChecked())
|
||||
{
|
||||
t = topt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1071,6 +1071,8 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
parameters,
|
||||
has2dScans);
|
||||
|
||||
std::set<int> validCameras = uKeysSet(clouds);
|
||||
|
||||
UDEBUG("");
|
||||
if(_canceled)
|
||||
{
|
||||
@@ -1915,60 +1917,63 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
std::map<int, std::vector<CameraModel> > cameraModels;
|
||||
for(std::map<int, Transform>::iterator jter=cameras.begin(); jter!=cameras.end(); ++jter)
|
||||
{
|
||||
std::vector<CameraModel> models;
|
||||
StereoCameraModel stereoModel;
|
||||
bool cacheHasCompressedImage = false;
|
||||
if(cachedSignatures.contains(jter->first))
|
||||
if(validCameras.find(jter->first) != validCameras.end())
|
||||
{
|
||||
const SensorData & data = cachedSignatures.find(jter->first)->sensorData();
|
||||
models = data.cameraModels();
|
||||
stereoModel = data.stereoCameraModel();
|
||||
cacheHasCompressedImage = !data.imageCompressed().empty();
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
_dbDriver->getCalibration(jter->first, models, stereoModel);
|
||||
}
|
||||
|
||||
if(stereoModel.isValidForProjection())
|
||||
{
|
||||
models.clear();
|
||||
models.push_back(stereoModel.left());
|
||||
}
|
||||
else if(models.size() == 0 || !models[0].isValidForProjection())
|
||||
{
|
||||
models.clear();
|
||||
}
|
||||
if(!jter->second.isNull() && models.size())
|
||||
{
|
||||
if(models[0].imageWidth() == 0 || models[0].imageHeight() == 0)
|
||||
std::vector<CameraModel> models;
|
||||
StereoCameraModel stereoModel;
|
||||
bool cacheHasCompressedImage = false;
|
||||
if(cachedSignatures.contains(jter->first))
|
||||
{
|
||||
// we are using an old database format (image size not saved in calibrations), we should
|
||||
// uncompress images to get their size
|
||||
cv::Mat img;
|
||||
if(cacheHasCompressedImage)
|
||||
{
|
||||
cachedSignatures.find(jter->first)->sensorData().uncompressDataConst(&img, 0);
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(jter->first, data, true, false, false, false);
|
||||
data.uncompressDataConst(&img, 0);
|
||||
}
|
||||
cv::Size imageSize = img.size();
|
||||
imageSize.width /= models.size();
|
||||
for(unsigned int i=0; i<models.size(); ++i)
|
||||
{
|
||||
models[i].setImageSize(imageSize);
|
||||
}
|
||||
|
||||
const SensorData & data = cachedSignatures.find(jter->first)->sensorData();
|
||||
models = data.cameraModels();
|
||||
stereoModel = data.stereoCameraModel();
|
||||
cacheHasCompressedImage = !data.imageCompressed().empty();
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
_dbDriver->getCalibration(jter->first, models, stereoModel);
|
||||
}
|
||||
|
||||
if(models[0].imageWidth() != 0 && models[0].imageHeight() != 0)
|
||||
if(stereoModel.isValidForProjection())
|
||||
{
|
||||
cameraPoses.insert(std::make_pair(jter->first, jter->second));
|
||||
cameraModels.insert(std::make_pair(jter->first, models));
|
||||
models.clear();
|
||||
models.push_back(stereoModel.left());
|
||||
}
|
||||
else if(models.size() == 0 || !models[0].isValidForProjection())
|
||||
{
|
||||
models.clear();
|
||||
}
|
||||
if(!jter->second.isNull() && models.size())
|
||||
{
|
||||
if(models[0].imageWidth() == 0 || models[0].imageHeight() == 0)
|
||||
{
|
||||
// we are using an old database format (image size not saved in calibrations), we should
|
||||
// uncompress images to get their size
|
||||
cv::Mat img;
|
||||
if(cacheHasCompressedImage)
|
||||
{
|
||||
cachedSignatures.find(jter->first)->sensorData().uncompressDataConst(&img, 0);
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(jter->first, data, true, false, false, false);
|
||||
data.uncompressDataConst(&img, 0);
|
||||
}
|
||||
cv::Size imageSize = img.size();
|
||||
imageSize.width /= models.size();
|
||||
for(unsigned int i=0; i<models.size(); ++i)
|
||||
{
|
||||
models[i].setImageSize(imageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(models[0].imageWidth() != 0 && models[0].imageHeight() != 0)
|
||||
{
|
||||
cameraPoses.insert(std::make_pair(jter->first, jter->second));
|
||||
cameraModels.insert(std::make_pair(jter->first, models));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-10
@@ -1120,8 +1120,13 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
|
||||
bool inlier = odom.info().words.find(iter->first) != odom.info().words.end();
|
||||
(*cloud)[i].r = inlier?0:255;
|
||||
(*cloud)[i].g = 255;
|
||||
(*cloud)[i++].b = 0;
|
||||
(*cloud)[i].b = 0;
|
||||
if(!_preferencesDialog->isOdomOnlyInliersShown() || inlier)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
cloud->resize(i);
|
||||
|
||||
_cloudViewer->addCloud("featuresOdom", cloud, _odometryCorrection);
|
||||
_cloudViewer->setCloudVisibility("featuresOdom", true);
|
||||
@@ -1185,10 +1190,25 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
|
||||
{
|
||||
if(odom.info().type == 0)
|
||||
{
|
||||
_ui->imageView_odometry->setFeatures(
|
||||
odom.info().words,
|
||||
odom.data().depthRaw(),
|
||||
Qt::yellow);
|
||||
if(_preferencesDialog->isOdomOnlyInliersShown())
|
||||
{
|
||||
std::multimap<int, cv::KeyPoint> kpInliers;
|
||||
for(unsigned int i=0; i<odom.info().wordInliers.size(); ++i)
|
||||
{
|
||||
kpInliers.insert(*odom.info().words.find(odom.info().wordInliers[i]));
|
||||
}
|
||||
_ui->imageView_odometry->setFeatures(
|
||||
kpInliers,
|
||||
odom.data().depthRaw(),
|
||||
Qt::green);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ui->imageView_odometry->setFeatures(
|
||||
odom.info().words,
|
||||
odom.data().depthRaw(),
|
||||
Qt::yellow);
|
||||
}
|
||||
}
|
||||
else if(odom.info().type == 1)
|
||||
{
|
||||
@@ -1238,7 +1258,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
|
||||
|
||||
if(odom.info().type == 0)
|
||||
{
|
||||
if(_ui->imageView_odometry->isFeaturesShown())
|
||||
if(_ui->imageView_odometry->isFeaturesShown() && !_preferencesDialog->isOdomOnlyInliersShown())
|
||||
{
|
||||
for(unsigned int i=0; i<odom.info().wordMatches.size(); ++i)
|
||||
{
|
||||
@@ -5179,7 +5199,7 @@ void MainWindow::postProcessing()
|
||||
if(!msg.empty())
|
||||
{
|
||||
UWARN("%s", msg.c_str());
|
||||
_initProgressDialog->appendText(tr("%s").arg(msg.c_str()));
|
||||
_initProgressDialog->appendText(tr("%1").arg(msg.c_str()));
|
||||
QApplication::processEvents();
|
||||
updateConstraint = false;
|
||||
}
|
||||
@@ -6678,7 +6698,7 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
}
|
||||
}
|
||||
actions = _ui->menuFile->actions();
|
||||
if(actions.size()==17)
|
||||
if(actions.size()==16)
|
||||
{
|
||||
if(actions.at(2)->isSeparator())
|
||||
{
|
||||
@@ -6688,9 +6708,9 @@ void MainWindow::changeState(MainWindow::State newState)
|
||||
{
|
||||
UWARN("Menu File separators have not the same order.");
|
||||
}
|
||||
if(actions.at(13)->isSeparator())
|
||||
if(actions.at(12)->isSeparator())
|
||||
{
|
||||
actions.at(13)->setVisible(!monitoring);
|
||||
actions.at(12)->setVisible(!monitoring);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -306,6 +306,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
connect(_ui->checkBox_cacheStatistics, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->checkBox_notifyWhenNewGlobalPathIsReceived, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->spinBox_odomQualityWarnThr, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->checkBox_odom_onlyInliersShown, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->checkBox_posteriorGraphView, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->checkbox_odomDisabled, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
connect(_ui->odom_registration, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteGeneralPanel()));
|
||||
@@ -785,6 +786,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
|
||||
// Registration
|
||||
_ui->loopClosure_bowVarianceFromInliersCount->setObjectName(Parameters::kRegVarianceFromInliersCount().c_str());
|
||||
_ui->reg_varianceNormalized->setObjectName(Parameters::kRegVarianceNormalized().c_str());
|
||||
_ui->comboBox_registrationStrategy->setObjectName(Parameters::kRegStrategy().c_str());
|
||||
_ui->loopClosure_bowForce2D->setObjectName(Parameters::kRegForce3DoF().c_str());
|
||||
|
||||
@@ -1255,6 +1257,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
|
||||
_ui->checkBox_imageRejectedShown->setChecked(true);
|
||||
_ui->checkBox_imageHighestHypShown->setChecked(false);
|
||||
_ui->spinBox_odomQualityWarnThr->setValue(50);
|
||||
_ui->checkBox_odom_onlyInliersShown->setChecked(false);
|
||||
_ui->checkBox_posteriorGraphView->setChecked(true);
|
||||
_ui->checkbox_odomDisabled->setChecked(false);
|
||||
_ui->checkbox_groundTruthAlign->setChecked(true);
|
||||
@@ -1651,6 +1654,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
|
||||
_ui->checkBox_cacheStatistics->setChecked(settings.value("figure_cache", _ui->checkBox_cacheStatistics->isChecked()).toBool());
|
||||
_ui->checkBox_notifyWhenNewGlobalPathIsReceived->setChecked(settings.value("notifyNewGlobalPath", _ui->checkBox_notifyWhenNewGlobalPathIsReceived->isChecked()).toBool());
|
||||
_ui->spinBox_odomQualityWarnThr->setValue(settings.value("odomQualityThr", _ui->spinBox_odomQualityWarnThr->value()).toInt());
|
||||
_ui->checkBox_odom_onlyInliersShown->setChecked(settings.value("odomOnlyInliersShown", _ui->checkBox_odom_onlyInliersShown->isChecked()).toBool());
|
||||
_ui->checkBox_posteriorGraphView->setChecked(settings.value("posteriorGraphView", _ui->checkBox_posteriorGraphView->isChecked()).toBool());
|
||||
_ui->checkbox_odomDisabled->setChecked(settings.value("odomDisabled", _ui->checkbox_odomDisabled->isChecked()).toBool());
|
||||
_ui->odom_registration->setCurrentIndex(settings.value("odomRegistration", _ui->odom_registration->currentIndex()).toInt());
|
||||
@@ -2037,6 +2041,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
|
||||
settings.setValue("figure_cache", _ui->checkBox_cacheStatistics->isChecked());
|
||||
settings.setValue("notifyNewGlobalPath", _ui->checkBox_notifyWhenNewGlobalPathIsReceived->isChecked());
|
||||
settings.setValue("odomQualityThr", _ui->spinBox_odomQualityWarnThr->value());
|
||||
settings.setValue("odomOnlyInliersShown", _ui->checkBox_odom_onlyInliersShown->isChecked());
|
||||
settings.setValue("posteriorGraphView", _ui->checkBox_posteriorGraphView->isChecked());
|
||||
settings.setValue("odomDisabled", _ui->checkbox_odomDisabled->isChecked());
|
||||
settings.setValue("odomRegistration", _ui->odom_registration->currentIndex());
|
||||
@@ -4026,6 +4031,10 @@ int PreferencesDialog::getOdomQualityWarnThr() const
|
||||
{
|
||||
return _ui->spinBox_odomQualityWarnThr->value();
|
||||
}
|
||||
bool PreferencesDialog::isOdomOnlyInliersShown() const
|
||||
{
|
||||
return _ui->checkBox_odom_onlyInliersShown->isChecked();
|
||||
}
|
||||
bool PreferencesDialog::isPosteriorGraphView() const
|
||||
{
|
||||
return _ui->checkBox_posteriorGraphView->isChecked();
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-667</y>
|
||||
<y>0</y>
|
||||
<width>673</width>
|
||||
<height>2747</height>
|
||||
</rect>
|
||||
@@ -86,7 +86,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>18</number>
|
||||
<number>19</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_22">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
|
||||
@@ -272,7 +272,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Loop Closure Detection View</string>
|
||||
<string>Loop Closure Detection</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_31" columnstretch="0,1">
|
||||
<item row="1" column="0">
|
||||
@@ -371,16 +371,15 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="groupBox_21">
|
||||
<property name="title">
|
||||
<string>3D Map View</string>
|
||||
<string>Odometry</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_38" columnstretch="0,1">
|
||||
<layout class="QGridLayout" name="gridLayout_85" columnstretch="0,1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_86">
|
||||
<widget class="QLabel" name="label_369">
|
||||
<property name="text">
|
||||
<string>Odometry warning theshold:
|
||||
Show a yellow background when the number of odometry inliers goes under this threshold. If 0, it is ignored. You can see the current odometry inliers count under Statistics view -> General -> Odom inliers.</string>
|
||||
<string>Show only inliers.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -391,6 +390,30 @@ Show a yellow background when the number of odometry inliers goes under this thr
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_odom_onlyInliersShown">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_159">
|
||||
<property name="text">
|
||||
<string>Warning theshold:
|
||||
Show a yellow background when the number of odometry inliers goes under this threshold. If 0, it is ignored. You can see the current odometry inliers count under Statistics view -> General -> Odom inliers.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="spinBox_odomQualityWarnThr">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
@@ -2678,7 +2701,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget_src">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_41">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_64">
|
||||
@@ -2788,7 +2811,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget_rgbd">
|
||||
<property name="currentIndex">
|
||||
<number>6</number>
|
||||
<number>7</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_32">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_63">
|
||||
@@ -3480,7 +3503,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
<string>For RGBD-SLAM datasets, it is 5.</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
@@ -10763,6 +10786,26 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_370">
|
||||
<property name="text">
|
||||
<string>Normalize covariance values. Position variances are multiplied by norm of the transform and orientation variances are multiplied by angle of the transform.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="reg_varianceNormalized">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user