Added "NearestNeighbor/7ConvertBinToFloat" parameter: This will convert binary descriptors to float so that vocabulary approaches with KD-Tree or K-means can be used with binary descriptors like Brief/ORB/FREAK (use MANHATTAN_L1 too)
This commit is contained in:
parent
138d004169
commit
91bce9ac69
@ -234,6 +234,8 @@ class FINDOBJECT_EXP Settings
|
|||||||
PARAMETER(NearestNeighbor, 4nndrRatio, float, 0.8f, "Nearest neighbor distance ratio.");
|
PARAMETER(NearestNeighbor, 4nndrRatio, float, 0.8f, "Nearest neighbor distance ratio.");
|
||||||
PARAMETER(NearestNeighbor, 5minDistanceUsed, bool, false, "Minimum distance with the nearest descriptor to accept a match.");
|
PARAMETER(NearestNeighbor, 5minDistanceUsed, bool, false, "Minimum distance with the nearest descriptor to accept a match.");
|
||||||
PARAMETER(NearestNeighbor, 6minDistance, float, 1.6f, "Minimum distance. You can look at top of this panel where minimum and maximum distances are shown to properly set this parameter depending of the descriptor used.");
|
PARAMETER(NearestNeighbor, 6minDistance, float, 1.6f, "Minimum distance. You can look at top of this panel where minimum and maximum distances are shown to properly set this parameter depending of the descriptor used.");
|
||||||
|
PARAMETER(NearestNeighbor, 7ConvertBinToFloat, bool, false, "Convert binary descriptor to float before quantization, so you can use FLANN strategies with them.");
|
||||||
|
|
||||||
|
|
||||||
PARAMETER(NearestNeighbor, BruteForce_gpu, bool, false, "Brute force GPU");
|
PARAMETER(NearestNeighbor, BruteForce_gpu, bool, false, "Brute force GPU");
|
||||||
|
|
||||||
|
|||||||
@ -1368,7 +1368,8 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
|||||||
vocabulary_->size() &&
|
vocabulary_->size() &&
|
||||||
!vocabulary_->indexedDescriptors().empty() &&
|
!vocabulary_->indexedDescriptors().empty() &&
|
||||||
vocabulary_->indexedDescriptors().cols == info.sceneDescriptors_.cols &&
|
vocabulary_->indexedDescriptors().cols == info.sceneDescriptors_.cols &&
|
||||||
vocabulary_->indexedDescriptors().type() == info.sceneDescriptors_.type();
|
(vocabulary_->indexedDescriptors().type() == info.sceneDescriptors_.type() ||
|
||||||
|
(Settings::getNearestNeighbor_7ConvertBinToFloat() && vocabulary_->indexedDescriptors().type() == CV_32FC1));
|
||||||
|
|
||||||
// COMPARE
|
// COMPARE
|
||||||
UDEBUG("COMPARE");
|
UDEBUG("COMPARE");
|
||||||
|
|||||||
@ -482,7 +482,7 @@ void ParametersToolBox::addParameter(QVBoxLayout * layout,
|
|||||||
QCheckBox * widget = new QCheckBox(this);
|
QCheckBox * widget = new QCheckBox(this);
|
||||||
widget->setChecked(value);
|
widget->setChecked(value);
|
||||||
widget->setObjectName(key);
|
widget->setObjectName(key);
|
||||||
connect(widget, SIGNAL(stateChanged(int)), this, SLOT(changeParameter(int)));
|
connect(widget, SIGNAL(toggled(bool)), this, SLOT(changeParameter(bool)));
|
||||||
addParameter(layout, key, widget);
|
addParameter(layout, key, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,17 +549,33 @@ void ParametersToolBox::changeParameter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParametersToolBox::changeParameter(const int & value)
|
void ParametersToolBox::changeParameter(bool value)
|
||||||
{
|
{
|
||||||
if(sender())
|
if(sender())
|
||||||
{
|
{
|
||||||
QStringList paramChanged;
|
// Workaround as stateChanged(int) is not always emitted, using toggled(bool) instead
|
||||||
QComboBox * comboBox = qobject_cast<QComboBox*>(sender());
|
changeParameter(sender(), value?Qt::Checked:Qt::Unchecked);
|
||||||
QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender());
|
}
|
||||||
if(comboBox)
|
}
|
||||||
|
|
||||||
|
void ParametersToolBox::changeParameter(int value)
|
||||||
|
{
|
||||||
|
if(sender())
|
||||||
{
|
{
|
||||||
|
changeParameter(sender(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParametersToolBox::changeParameter(QObject * sender, int value)
|
||||||
|
{
|
||||||
|
if(sender)
|
||||||
|
{
|
||||||
|
QStringList paramChanged;
|
||||||
|
QComboBox * comboBox = qobject_cast<QComboBox*>(sender);
|
||||||
|
QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender);
|
||||||
|
|
||||||
bool descriptorChanged = false;
|
bool descriptorChanged = false;
|
||||||
if(comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0)
|
if(comboBox && comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0)
|
||||||
{
|
{
|
||||||
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
|
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
|
||||||
if(comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0 &&
|
if(comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0 &&
|
||||||
@ -597,13 +613,15 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
|
|
||||||
bool nnStrategyChanged = false;
|
bool nnStrategyChanged = false;
|
||||||
//verify binary issue with nearest neighbor strategy
|
//verify binary issue with nearest neighbor strategy
|
||||||
if(comboBox->objectName().compare(Settings::kFeature2D_2Descriptor()) == 0 ||
|
if((comboBox && (comboBox->objectName().compare(Settings::kFeature2D_2Descriptor()) == 0 ||
|
||||||
comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 ||
|
comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0)) ||
|
||||||
descriptorChanged)
|
descriptorChanged ||
|
||||||
|
(checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0))
|
||||||
{
|
{
|
||||||
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
|
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
|
||||||
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
|
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
|
||||||
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
|
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
|
||||||
|
QCheckBox * binToFloatCheckbox = (QCheckBox*)this->getParameterWidget(Settings::kNearestNeighbor_7ConvertBinToFloat());
|
||||||
bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 ||
|
bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 ||
|
||||||
descriptorBox->currentText().compare("Brief") == 0 ||
|
descriptorBox->currentText().compare("Brief") == 0 ||
|
||||||
descriptorBox->currentText().compare("BRISK") == 0 ||
|
descriptorBox->currentText().compare("BRISK") == 0 ||
|
||||||
@ -611,7 +629,8 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
descriptorBox->currentText().compare("AKAZE") == 0 ||
|
descriptorBox->currentText().compare("AKAZE") == 0 ||
|
||||||
descriptorBox->currentText().compare("LATCH") == 0 ||
|
descriptorBox->currentText().compare("LATCH") == 0 ||
|
||||||
descriptorBox->currentText().compare("LUCID") == 0;
|
descriptorBox->currentText().compare("LUCID") == 0;
|
||||||
if(isBinaryDescriptor && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0)
|
bool binToFloat = binToFloatCheckbox->isChecked();
|
||||||
|
if(isBinaryDescriptor && !binToFloat && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("Warning"),
|
tr("Warning"),
|
||||||
@ -631,7 +650,7 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
||||||
nnBox->blockSignals(false);
|
nnBox->blockSignals(false);
|
||||||
distBox->blockSignals(false);
|
distBox->blockSignals(false);
|
||||||
if(sender() == nnBox)
|
if(sender == nnBox)
|
||||||
{
|
{
|
||||||
this->updateParametersVisibility();
|
this->updateParametersVisibility();
|
||||||
return;
|
return;
|
||||||
@ -640,7 +659,39 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
paramChanged.append(Settings::kNearestNeighbor_1Strategy());
|
paramChanged.append(Settings::kNearestNeighbor_1Strategy());
|
||||||
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
|
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
|
||||||
}
|
}
|
||||||
else if(!isBinaryDescriptor && nnBox->currentText().compare("Lsh") == 0)
|
else if((!isBinaryDescriptor || binToFloat) && nnBox->currentText().compare("Lsh") == 0)
|
||||||
|
{
|
||||||
|
if(binToFloat)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this,
|
||||||
|
tr("Warning"),
|
||||||
|
tr("Current selected descriptor type (\"%1\") is binary, but binary to float descriptors conversion is activated while nearest neighbor strategy is (\"%2\").\n"
|
||||||
|
"Disabling binary to float descriptors conversion and use Hamming distance (by default).")
|
||||||
|
.arg(descriptorBox->currentText())
|
||||||
|
.arg(nnBox->currentText()));
|
||||||
|
|
||||||
|
binToFloatCheckbox->blockSignals(true);
|
||||||
|
if(checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0)
|
||||||
|
{
|
||||||
|
Settings::setParameter(checkBox->objectName(), false);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paramChanged.append(Settings::kNearestNeighbor_7ConvertBinToFloat());
|
||||||
|
}
|
||||||
|
this->updateParameter(Settings::kNearestNeighbor_7ConvertBinToFloat());
|
||||||
|
binToFloatCheckbox->blockSignals(false);
|
||||||
|
|
||||||
|
QString tmp = Settings::getNearestNeighbor_2Distance_type();
|
||||||
|
*tmp.begin() = '8'; // set HAMMING
|
||||||
|
Settings::setNearestNeighbor_2Distance_type(tmp);
|
||||||
|
distBox->blockSignals(true);
|
||||||
|
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
||||||
|
distBox->blockSignals(false);
|
||||||
|
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("Warning"),
|
tr("Warning"),
|
||||||
@ -648,6 +699,7 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
"Falling back to \"KDTree\" nearest neighbor strategy with Euclidean_L2 distance (by default).")
|
"Falling back to \"KDTree\" nearest neighbor strategy with Euclidean_L2 distance (by default).")
|
||||||
.arg(descriptorBox->currentText())
|
.arg(descriptorBox->currentText())
|
||||||
.arg(nnBox->currentText()));
|
.arg(nnBox->currentText()));
|
||||||
|
|
||||||
QString tmp = Settings::getNearestNeighbor_1Strategy();
|
QString tmp = Settings::getNearestNeighbor_1Strategy();
|
||||||
*tmp.begin() = '1'; // set KDTree
|
*tmp.begin() = '1'; // set KDTree
|
||||||
Settings::setNearestNeighbor_1Strategy(tmp);
|
Settings::setNearestNeighbor_1Strategy(tmp);
|
||||||
@ -660,7 +712,7 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
||||||
nnBox->blockSignals(false);
|
nnBox->blockSignals(false);
|
||||||
distBox->blockSignals(false);
|
distBox->blockSignals(false);
|
||||||
if(sender() == nnBox)
|
if(sender == nnBox)
|
||||||
{
|
{
|
||||||
this->updateParametersVisibility();
|
this->updateParametersVisibility();
|
||||||
return;
|
return;
|
||||||
@ -670,11 +722,12 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
|
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Distance issue when using nearest neighbor strategy using CV_32F type, though Lsh support all type (doesn't crash at least)
|
// Distance issue when using nearest neighbor strategy using CV_32F type, though Lsh support all type (doesn't crash at least)
|
||||||
if(nnStrategyChanged ||
|
if(nnStrategyChanged ||
|
||||||
comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 ||
|
(comboBox && (comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 ||
|
||||||
comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0)
|
comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0)))
|
||||||
{
|
{
|
||||||
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
|
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
|
||||||
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
|
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
|
||||||
@ -692,7 +745,7 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
distBox->blockSignals(true);
|
distBox->blockSignals(true);
|
||||||
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
|
||||||
distBox->blockSignals(false);
|
distBox->blockSignals(false);
|
||||||
if(sender() == distBox)
|
if(sender == distBox)
|
||||||
{
|
{
|
||||||
this->updateParametersVisibility();
|
this->updateParametersVisibility();
|
||||||
return;
|
return;
|
||||||
@ -701,22 +754,25 @@ void ParametersToolBox::changeParameter(const int & value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(comboBox)
|
||||||
|
{
|
||||||
QStringList items;
|
QStringList items;
|
||||||
for(int i=0; i<comboBox->count(); ++i)
|
for(int i=0; i<comboBox->count(); ++i)
|
||||||
{
|
{
|
||||||
items.append(comboBox->itemText(i));
|
items.append(comboBox->itemText(i));
|
||||||
}
|
}
|
||||||
QString merged = QString::number(value) + QString(":") + items.join(";");
|
QString merged = QString::number(value) + QString(":") + items.join(";");
|
||||||
Settings::setParameter(sender()->objectName(), merged);
|
Settings::setParameter(sender->objectName(), merged);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(checkBox)
|
||||||
|
{
|
||||||
|
Settings::setParameter(sender->objectName(), value==Qt::Checked?true:false);
|
||||||
|
}
|
||||||
|
|
||||||
this->updateParametersVisibility();
|
this->updateParametersVisibility();
|
||||||
}
|
|
||||||
else if(checkBox)
|
|
||||||
{
|
|
||||||
Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false);
|
|
||||||
}
|
|
||||||
|
|
||||||
paramChanged.append(sender()->objectName());
|
paramChanged.append(sender->objectName());
|
||||||
Q_EMIT parametersChanged(paramChanged);
|
Q_EMIT parametersChanged(paramChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,13 +55,16 @@ private:
|
|||||||
void addParameter(QVBoxLayout * layout, const QString & key, const bool & value);
|
void addParameter(QVBoxLayout * layout, const QString & key, const bool & value);
|
||||||
void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget);
|
void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget);
|
||||||
|
|
||||||
|
void changeParameter(QObject * sender, int value);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void parametersChanged(const QStringList & name);
|
void parametersChanged(const QStringList & name);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void changeParameter();
|
void changeParameter();
|
||||||
void changeParameter(const QString & value);
|
void changeParameter(const QString & value);
|
||||||
void changeParameter(const int & value);
|
void changeParameter(bool value);
|
||||||
|
void changeParameter(int value);
|
||||||
void resetCurrentPage();
|
void resetCurrentPage();
|
||||||
void resetAllPages();
|
void resetAllPages();
|
||||||
|
|
||||||
|
|||||||
@ -144,14 +144,24 @@ bool Vocabulary::load(const QString & filename)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptors, int objectId)
|
QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptorsIn, int objectId)
|
||||||
{
|
{
|
||||||
QMultiMap<int, int> words;
|
QMultiMap<int, int> words;
|
||||||
if (descriptors.empty())
|
if (descriptorsIn.empty())
|
||||||
{
|
{
|
||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cv::Mat descriptors;
|
||||||
|
if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
|
||||||
|
{
|
||||||
|
descriptorsIn.convertTo(descriptors, CV_32F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
descriptors = descriptorsIn;
|
||||||
|
}
|
||||||
|
|
||||||
if(Settings::getGeneral_vocabularyIncremental() || Settings::getGeneral_vocabularyFixed())
|
if(Settings::getGeneral_vocabularyIncremental() || Settings::getGeneral_vocabularyFixed())
|
||||||
{
|
{
|
||||||
int k = 2;
|
int k = 2;
|
||||||
@ -350,10 +360,20 @@ void Vocabulary::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vocabulary::search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k)
|
void Vocabulary::search(const cv::Mat & descriptorsIn, cv::Mat & results, cv::Mat & dists, int k)
|
||||||
{
|
{
|
||||||
if(!indexedDescriptors_.empty())
|
if(!indexedDescriptors_.empty())
|
||||||
{
|
{
|
||||||
|
cv::Mat descriptors;
|
||||||
|
if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
|
||||||
|
{
|
||||||
|
descriptorsIn.convertTo(descriptors, CV_32F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
descriptors = descriptorsIn;
|
||||||
|
}
|
||||||
|
|
||||||
UASSERT(descriptors.type() == indexedDescriptors_.type() && descriptors.cols == indexedDescriptors_.cols);
|
UASSERT(descriptors.type() == indexedDescriptors_.type() && descriptors.cols == indexedDescriptors_.cols);
|
||||||
|
|
||||||
if(Settings::isBruteForceNearestNeighbor())
|
if(Settings::isBruteForceNearestNeighbor())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user