Added BruteForce nearest neighbor (with GPU option), which is now the default for binary descriptors

CMake: Detecting if openCV is built with nonfree module, if yes, SIFT and SURF can be used

git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@411 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
matlabbe 2014-10-24 02:46:03 +00:00
parent 783173bf43
commit 4d3b9e88b2
6 changed files with 345 additions and 267 deletions

View File

@ -84,6 +84,10 @@ FIND_PACKAGE(OpenCV REQUIRED) # tested on 2.3.1
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) # tested on Qt4.8
ADD_DEFINITIONS(-DQT_NO_KEYWORDS) # To avoid conflicts with boost signals used in ROS
IF(OPENCV_NONFREE_FOUND)
ADD_DEFINITIONS(-DWITH_NONFREE)
ENDIF(OPENCV_NONFREE_FOUND)
####### OSX BUNDLE CMAKE_INSTALL_PREFIX #######
IF(APPLE)
OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF)
@ -218,6 +222,11 @@ MESSAGE(STATUS "--------------------------------------------")
MESSAGE(STATUS "Info :")
MESSAGE(STATUS " CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
MESSAGE(STATUS " CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
IF(OPENCV_NONFREE_FOUND)
MESSAGE(STATUS " With OpenCV nonfree module (SIFT/SURF) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV nonfree module (SIFT/SURF) = NO (not found)")
ENDIF()
IF(APPLE)
MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}")
ENDIF(APPLE)

View File

@ -94,8 +94,13 @@ class FINDOBJECT_EXP Settings
PARAMETER(Camera, 9queueSize, int, 1, "Maximum images buffered from TCP. If 0, all images are buffered.");
//List format : [Index:item0;item1;item3;...]
#ifdef WITH_NONFREE
PARAMETER(Feature2D, 1Detector, QString, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK" , "Keypoint detector.");
PARAMETER(Feature2D, 2Descriptor, QString, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK", "Keypoint descriptor.");
#else
PARAMETER(Feature2D, 1Detector, QString, "1:Dense;Fast;GFTT;MSER;ORB;Star;BRISK" , "Keypoint detector.");
PARAMETER(Feature2D, 2Descriptor, QString, "0:Brief;ORB;BRISK;FREAK", "Keypoint descriptor.");
#endif
PARAMETER(Feature2D, 3MaxFeatures, int, 0, "Maximum features per image. If the number of features extracted is over this threshold, only X features with the highest response are kept. 0 means all features are kept.");
PARAMETER(Feature2D, 4Affine, bool, false, "(ASIFT) Extract features on multiple affine transformations of the image.");
PARAMETER(Feature2D, 5AffineCount, int, 6, "(ASIFT) Higher the value, more affine transformations will be done.");
@ -142,18 +147,13 @@ class FINDOBJECT_EXP Settings
PARAMETER(Feature2D, MSER_minMargin, double, 0.003, "");
PARAMETER(Feature2D, MSER_edgeBlurSize, int, 5, "");
#ifdef WITH_NONFREE
PARAMETER(Feature2D, SIFT_nfeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast).");
PARAMETER(Feature2D, SIFT_nOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution.");
PARAMETER(Feature2D, SIFT_contrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
PARAMETER(Feature2D, SIFT_edgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
PARAMETER(Feature2D, SIFT_sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
PARAMETER(Feature2D, Star_maxSize, int, 45, "");
PARAMETER(Feature2D, Star_responseThreshold, int, 30, "");
PARAMETER(Feature2D, Star_lineThresholdProjected, int, 10, "");
PARAMETER(Feature2D, Star_lineThresholdBinarized, int, 8, "");
PARAMETER(Feature2D, Star_suppressNonmaxSize, int, 5, "");
PARAMETER(Feature2D, SURF_hessianThreshold, double, 600.0, "Threshold for hessian keypoint detector used in SURF.");
PARAMETER(Feature2D, SURF_nOctaves, int, 4, "Number of pyramid octaves the keypoint detector will use.");
PARAMETER(Feature2D, SURF_nOctaveLayers, int, 2, "Number of octave layers within each octave.");
@ -161,6 +161,13 @@ class FINDOBJECT_EXP Settings
PARAMETER(Feature2D, SURF_upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).");
PARAMETER(Feature2D, SURF_gpu, bool, false, "GPU-SURF: Use GPU version of SURF. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
PARAMETER(Feature2D, SURF_keypointsRatio, float, 0.01f, "Used with SURF GPU.");
#endif
PARAMETER(Feature2D, Star_maxSize, int, 45, "");
PARAMETER(Feature2D, Star_responseThreshold, int, 30, "");
PARAMETER(Feature2D, Star_lineThresholdProjected, int, 10, "");
PARAMETER(Feature2D, Star_lineThresholdBinarized, int, 8, "");
PARAMETER(Feature2D, Star_suppressNonmaxSize, int, 5, "");
PARAMETER(Feature2D, BRISK_thresh, int, 30, "FAST/AGAST detection threshold score.");
PARAMETER(Feature2D, BRISK_octaves, int, 3, "Detection octaves. Use 0 to do single scale.");
@ -171,16 +178,23 @@ class FINDOBJECT_EXP Settings
PARAMETER(Feature2D, FREAK_patternScale, float, 22.0f, "Scaling of the description pattern.");
PARAMETER(Feature2D, FREAK_nOctaves, int, 4, "Number of octaves covered by the detected keypoints.");
PARAMETER(NearestNeighbor, 1Strategy, QString, "1:Linear;KDTree;KMeans;Composite;Autotuned;Lsh", "Nearest neighbor strategy.");
#ifdef WITH_NONFREE
PARAMETER(NearestNeighbor, 1Strategy, QString, "1:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "Nearest neighbor strategy.");
PARAMETER(NearestNeighbor, 2Distance_type, QString, "0:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "Distance type.");
#else
PARAMETER(NearestNeighbor, 1Strategy, QString, "6:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "Nearest neighbor strategy.");
PARAMETER(NearestNeighbor, 2Distance_type, QString, "1:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "Distance type.");
#endif
PARAMETER(NearestNeighbor, 3nndrRatioUsed, bool, true, "Nearest neighbor distance ratio approach to accept the best match.");
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, 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, 7search_checks, int, 32, "The number of times the tree(s) in the index should be recursively traversed. A higher value for this parameter would give better search precision, but also take more time. If automatic configuration was used when the index was created, the number of checks required to achieve the specified precision was also computed, in which case this parameter is ignored.");
PARAMETER(NearestNeighbor, 8search_eps, float, 0, "");
PARAMETER(NearestNeighbor, 9search_sorted, bool, true, "");
PARAMETER(NearestNeighbor, BruteForce_gpu, bool, false, "Brute force GPU");
PARAMETER(NearestNeighbor, search_checks, int, 32, "The number of times the tree(s) in the index should be recursively traversed. A higher value for this parameter would give better search precision, but also take more time. If automatic configuration was used when the index was created, the number of checks required to achieve the specified precision was also computed, in which case this parameter is ignored.");
PARAMETER(NearestNeighbor, search_eps, float, 0, "");
PARAMETER(NearestNeighbor, search_sorted, bool, true, "");
PARAMETER(NearestNeighbor, KDTree_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16].");
@ -261,6 +275,7 @@ public:
static QString currentDetectorType();
static QString currentNearestNeighborType();
static bool isBruteForceNearestNeighbor();
static cv::flann::IndexParams * createFlannIndexParams();
static cvflann::flann_distance_t getFlannDistanceType();
static cv::flann::SearchParams getFlannSearchParams();

View File

@ -135,14 +135,18 @@ MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * paren
if(cv::gpu::getCudaEnabledDeviceCount() == 0)
{
#ifdef WITH_NONFREE
ui_->toolBox->updateParameter(Settings::kFeature2D_SURF_gpu());
ui_->toolBox->updateParameter(Settings::kFeature2D_Fast_gpu());
ui_->toolBox->updateParameter(Settings::kFeature2D_ORB_gpu());
ui_->toolBox->getParameterWidget(Settings::kFeature2D_SURF_gpu())->setEnabled(false);
ui_->toolBox->getParameterWidget(Settings::kFeature2D_SURF_keypointsRatio())->setEnabled(false);
#endif
ui_->toolBox->updateParameter(Settings::kFeature2D_Fast_gpu());
ui_->toolBox->updateParameter(Settings::kFeature2D_ORB_gpu());
ui_->toolBox->updateParameter(Settings::kNearestNeighbor_BruteForce_gpu());
ui_->toolBox->getParameterWidget(Settings::kFeature2D_Fast_gpu())->setEnabled(false);
ui_->toolBox->getParameterWidget(Settings::kFeature2D_Fast_keypointsRatio())->setEnabled(false);
ui_->toolBox->getParameterWidget(Settings::kFeature2D_ORB_gpu())->setEnabled(false);
ui_->toolBox->getParameterWidget(Settings::kNearestNeighbor_BruteForce_gpu())->setEnabled(false);
}
connect((QDoubleSpinBox*)ui_->toolBox->getParameterWidget(Settings::kCamera_4imageRate()),

View File

@ -204,6 +204,16 @@ void ParametersToolBox::updateParametersVisibility()
else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
{
((QWidget*)objects[i])->setVisible(false);
if(nnBox->currentIndex() < 6 && objects[i]->objectName().split('/').at(1).contains("search"))
{
//show flann search parameters
((QWidget*)objects[i])->setVisible(true);
}
}
else if(objects[i]->objectName().split('/').at(1).contains("Distance_type"))
{
// don't show distance when bruteforce is selected
((QWidget*)objects[i])->setVisible(nnBox->currentIndex() != 6);
}
}
}
@ -494,16 +504,16 @@ void ParametersToolBox::changeParameter(const int & value)
descriptorBox->currentText().compare("Brief") == 0 ||
descriptorBox->currentText().compare("BRISK") == 0 ||
descriptorBox->currentText().compare("FREAK") == 0;
if(isBinaryDescriptor && nnBox->currentText().compare("Lsh") != 0)
if(isBinaryDescriptor && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0)
{
QMessageBox::warning(this,
tr("Warning"),
tr("Current selected descriptor type (\"%1\") is binary while nearest neighbor strategy is not (\"%2\").\n"
"Falling back to \"Lsh\" nearest neighbor strategy with Hamming distance (by default).")
"Falling back to \"BruteForce\" nearest neighbor strategy with Hamming distance (by default).")
.arg(descriptorBox->currentText())
.arg(nnBox->currentText()));
QString tmp = Settings::getNearestNeighbor_1Strategy();
*tmp.begin() = '5'; // set LSH
*tmp.begin() = '6'; // set BruteForce
Settings::setNearestNeighbor_1Strategy(tmp);
tmp = Settings::getNearestNeighbor_2Distance_type();
*tmp.begin() = '8'; // set HAMMING
@ -561,7 +571,7 @@ void ParametersToolBox::changeParameter(const int & value)
{
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
if(nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1)
if(nnBox->currentText().compare("BruteForce") != 0 && nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1)
{
QMessageBox::warning(this,
tr("Warning"),

View File

@ -33,9 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore/QStringList>
#include <QtCore/QDir>
#include <stdio.h>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#ifdef WITH_NONFREE
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/nonfree/gpu.hpp>
#endif
#include <opencv2/gpu/gpu.hpp>
namespace find_object {
@ -120,9 +122,12 @@ void Settings::loadSettings(const QString & fileName)
if(cv::gpu::getCudaEnabledDeviceCount() == 0)
{
#ifdef WITH_NONFREE
Settings::setFeature2D_SURF_gpu(false);
#endif
Settings::setFeature2D_Fast_gpu(false);
Settings::setFeature2D_ORB_gpu(false);
Settings::setNearestNeighbor_BruteForce_gpu(false);
}
}
@ -217,6 +222,7 @@ public:
cv::Mat & descriptors) = 0;
};
#ifdef WITH_NONFREE
class GPUSURF : public GPUFeature2D
{
public:
@ -291,6 +297,7 @@ public:
private:
cv::gpu::SURF_GPU surf_; // HACK: static because detectImpl() is const!
};
#endif
class GPUFAST : public GPUFeature2D
{
@ -416,168 +423,151 @@ KeypointDetector * Settings::createKeypointDetector()
if(ok)
{
QStringList strategies = split.last().split(';');
#ifdef WITH_NONFREE
if(strategies.size() == 9 && index>=0 && index<9)
#else
if(strategies.size() == 7 && index>=0 && index<7)
#endif
{
switch(index)
if(strategies.at(index).compare("Dense") == 0)
{
case 0:
if(strategies.at(index).compare("Dense") == 0)
detector = new cv::DenseFeatureDetector(
getFeature2D_Dense_initFeatureScale(),
getFeature2D_Dense_featureScaleLevels(),
getFeature2D_Dense_featureScaleMul(),
getFeature2D_Dense_initXyStep(),
getFeature2D_Dense_initImgBound(),
getFeature2D_Dense_varyXyStepWithScale(),
getFeature2D_Dense_varyImgBoundWithScale());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("Fast") == 0)
{
if(getFeature2D_Fast_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
detector = new cv::DenseFeatureDetector(
getFeature2D_Dense_initFeatureScale(),
getFeature2D_Dense_featureScaleLevels(),
getFeature2D_Dense_featureScaleMul(),
getFeature2D_Dense_initXyStep(),
getFeature2D_Dense_initImgBound(),
getFeature2D_Dense_varyXyStepWithScale(),
getFeature2D_Dense_varyImgBoundWithScale());
detectorGPU = new GPUFAST(
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s GPU", strategies.at(index).toStdString().c_str());
}
else
{
detector = new cv::FastFeatureDetector(
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 1:
if(strategies.at(index).compare("Fast") == 0)
}
else if(strategies.at(index).compare("GFTT") == 0)
{
detector = new cv::GFTTDetector(
getFeature2D_GFTT_maxCorners(),
getFeature2D_GFTT_qualityLevel(),
getFeature2D_GFTT_minDistance(),
getFeature2D_GFTT_blockSize(),
getFeature2D_GFTT_useHarrisDetector(),
getFeature2D_GFTT_k());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("MSER") == 0)
{
detector = new cv::MSER(
getFeature2D_MSER_delta(),
getFeature2D_MSER_minArea(),
getFeature2D_MSER_maxArea(),
getFeature2D_MSER_maxVariation(),
getFeature2D_MSER_minDiversity(),
getFeature2D_MSER_maxEvolution(),
getFeature2D_MSER_areaThreshold(),
getFeature2D_MSER_minMargin(),
getFeature2D_MSER_edgeBlurSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("ORB") == 0)
{
if(getFeature2D_ORB_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
if(getFeature2D_Fast_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
detectorGPU = new GPUFAST(
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s GPU", strategies.at(index).toStdString().c_str());
}
else
{
detector = new cv::FastFeatureDetector(
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
detectorGPU = new GPUORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize(),
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
break;
case 2:
if(strategies.at(index).compare("GFTT") == 0)
else
{
detector = new cv::GFTTDetector(
getFeature2D_GFTT_maxCorners(),
getFeature2D_GFTT_qualityLevel(),
getFeature2D_GFTT_minDistance(),
getFeature2D_GFTT_blockSize(),
getFeature2D_GFTT_useHarrisDetector(),
getFeature2D_GFTT_k());
detector = new cv::ORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 3:
if(strategies.at(index).compare("MSER") == 0)
}
else if(strategies.at(index).compare("Star") == 0)
{
detector = new cv::StarFeatureDetector(
getFeature2D_Star_maxSize(),
getFeature2D_Star_responseThreshold(),
getFeature2D_Star_lineThresholdProjected(),
getFeature2D_Star_lineThresholdBinarized(),
getFeature2D_Star_suppressNonmaxSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("BRISK") == 0)
{
detector = new cv::BRISK(
getFeature2D_BRISK_thresh(),
getFeature2D_BRISK_octaves(),
getFeature2D_BRISK_patternScale());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
#ifdef WITH_NONFREE
else if(strategies.at(index).compare("SIFT") == 0)
{
detector = new cv::SIFT(
getFeature2D_SIFT_nfeatures(),
getFeature2D_SIFT_nOctaveLayers(),
getFeature2D_SIFT_contrastThreshold(),
getFeature2D_SIFT_edgeThreshold(),
getFeature2D_SIFT_sigma());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("SURF") == 0)
{
if(getFeature2D_SURF_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
detector = new cv::MSER(
getFeature2D_MSER_delta(),
getFeature2D_MSER_minArea(),
getFeature2D_MSER_maxArea(),
getFeature2D_MSER_maxVariation(),
getFeature2D_MSER_minDiversity(),
getFeature2D_MSER_maxEvolution(),
getFeature2D_MSER_areaThreshold(),
getFeature2D_MSER_minMargin(),
getFeature2D_MSER_edgeBlurSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 4:
if(strategies.at(index).compare("ORB") == 0)
{
if(getFeature2D_ORB_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
detectorGPU = new GPUORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize(),
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
detector = new cv::ORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
}
break;
case 5:
if(strategies.at(index).compare("SIFT") == 0)
{
detector = new cv::SIFT(
getFeature2D_SIFT_nfeatures(),
getFeature2D_SIFT_nOctaveLayers(),
getFeature2D_SIFT_contrastThreshold(),
getFeature2D_SIFT_edgeThreshold(),
getFeature2D_SIFT_sigma());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 6:
if(strategies.at(index).compare("Star") == 0)
{
detector = new cv::StarFeatureDetector(
getFeature2D_Star_maxSize(),
getFeature2D_Star_responseThreshold(),
getFeature2D_Star_lineThresholdProjected(),
getFeature2D_Star_lineThresholdBinarized(),
getFeature2D_Star_suppressNonmaxSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 7:
if(strategies.at(index).compare("SURF") == 0)
{
if(getFeature2D_SURF_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
detectorGPU = new GPUSURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_keypointsRatio(),
getFeature2D_SURF_upright());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
detector = new cv::SURF(
detectorGPU = new GPUSURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_keypointsRatio(),
getFeature2D_SURF_upright());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
break;
case 8:
if(strategies.at(index).compare("BRISK") == 0)
else
{
detector = new cv::BRISK(
getFeature2D_BRISK_thresh(),
getFeature2D_BRISK_octaves(),
getFeature2D_BRISK_patternScale());
detector = new cv::SURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_upright());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
default:
break;
}
#endif
}
}
}
@ -606,113 +596,102 @@ DescriptorExtractor * Settings::createDescriptorExtractor()
if(ok)
{
QStringList strategies = split.last().split(';');
#ifdef WITH_NONFREE
if(strategies.size() == 6 && index>=0 && index<6)
#else
if(strategies.size() == 4 && index>=0 && index<4)
#endif
{
switch(index)
if(strategies.at(index).compare("Brief") == 0)
{
case 0:
if(strategies.at(index).compare("Brief") == 0)
{
extractor = new cv::BriefDescriptorExtractor(
getFeature2D_Brief_bytes());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 1:
if(strategies.at(index).compare("ORB") == 0)
{
if(getFeature2D_ORB_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
extractorGPU = new GPUORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize(),
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
extractor = new cv::ORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
}
break;
case 2:
if(strategies.at(index).compare("SIFT") == 0)
{
extractor = new cv::SIFT(
getFeature2D_SIFT_nfeatures(),
getFeature2D_SIFT_nOctaveLayers(),
getFeature2D_SIFT_contrastThreshold(),
getFeature2D_SIFT_edgeThreshold(),
getFeature2D_SIFT_sigma());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 3:
if(strategies.at(index).compare("SURF") == 0)
{
if(getFeature2D_SURF_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
extractorGPU = new GPUSURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_keypointsRatio(),
getFeature2D_SURF_upright());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
extractor = new cv::SURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_upright());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
}
break;
case 4:
if(strategies.at(index).compare("BRISK") == 0)
{
extractor = new cv::BRISK(
getFeature2D_BRISK_thresh(),
getFeature2D_BRISK_octaves(),
getFeature2D_BRISK_patternScale());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
case 5:
if(strategies.at(index).compare("FREAK") == 0)
{
extractor = new cv::FREAK(
getFeature2D_FREAK_orientationNormalized(),
getFeature2D_FREAK_scaleNormalized(),
getFeature2D_FREAK_patternScale(),
getFeature2D_FREAK_nOctaves());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
break;
default:
break;
extractor = new cv::BriefDescriptorExtractor(
getFeature2D_Brief_bytes());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("ORB") == 0)
{
if(getFeature2D_ORB_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
extractorGPU = new GPUORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize(),
getFeature2D_Fast_threshold(),
getFeature2D_Fast_nonmaxSuppression());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
extractor = new cv::ORB(
getFeature2D_ORB_nFeatures(),
getFeature2D_ORB_scaleFactor(),
getFeature2D_ORB_nLevels(),
getFeature2D_ORB_edgeThreshold(),
getFeature2D_ORB_firstLevel(),
getFeature2D_ORB_WTA_K(),
getFeature2D_ORB_scoreType(),
getFeature2D_ORB_patchSize());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
}
else if(strategies.at(index).compare("BRISK") == 0)
{
extractor = new cv::BRISK(
getFeature2D_BRISK_thresh(),
getFeature2D_BRISK_octaves(),
getFeature2D_BRISK_patternScale());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("FREAK") == 0)
{
extractor = new cv::FREAK(
getFeature2D_FREAK_orientationNormalized(),
getFeature2D_FREAK_scaleNormalized(),
getFeature2D_FREAK_patternScale(),
getFeature2D_FREAK_nOctaves());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
#ifdef WITH_NONFREE
else if(strategies.at(index).compare("SIFT") == 0)
{
extractor = new cv::SIFT(
getFeature2D_SIFT_nfeatures(),
getFeature2D_SIFT_nOctaveLayers(),
getFeature2D_SIFT_contrastThreshold(),
getFeature2D_SIFT_edgeThreshold(),
getFeature2D_SIFT_sigma());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
else if(strategies.at(index).compare("SURF") == 0)
{
if(getFeature2D_SURF_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
extractorGPU = new GPUSURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_keypointsRatio(),
getFeature2D_SURF_upright());
UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str());
}
else
{
extractor = new cv::SURF(
getFeature2D_SURF_hessianThreshold(),
getFeature2D_SURF_nOctaves(),
getFeature2D_SURF_nOctaveLayers(),
getFeature2D_SURF_extended(),
getFeature2D_SURF_upright());
UDEBUG("type=%s", strategies.at(index).toStdString().c_str());
}
}
#endif
}
}
}
@ -746,6 +725,27 @@ QString Settings::currentNearestNeighborType()
return getNearestNeighbor_1Strategy().split(':').last().split(';').at(index);
}
bool Settings::isBruteForceNearestNeighbor()
{
bool bruteForce = false;
QString str = getNearestNeighbor_1Strategy();
QStringList split = str.split(':');
if(split.size()==2)
{
bool ok = false;
int index = split.first().toInt(&ok);
if(ok)
{
QStringList strategies = split.last().split(';');
if(strategies.size() >= 7 && index == 6)
{
bruteForce = true;
}
}
}
return bruteForce;
}
cv::flann::IndexParams * Settings::createFlannIndexParams()
{
cv::flann::IndexParams * params = 0;
@ -758,7 +758,7 @@ cv::flann::IndexParams * Settings::createFlannIndexParams()
if(ok)
{
QStringList strategies = split.last().split(';');
if(strategies.size() == 6 && index>=0 && index<6)
if(strategies.size() >= 6 && index>=0 && index<6)
{
switch(index)
{
@ -884,9 +884,9 @@ cvflann::flann_distance_t Settings::getFlannDistanceType()
cv::flann::SearchParams Settings::getFlannSearchParams()
{
return cv::flann::SearchParams(
getNearestNeighbor_7search_checks(),
getNearestNeighbor_8search_eps(),
getNearestNeighbor_9search_sorted());
getNearestNeighbor_search_checks(),
getNearestNeighbor_search_eps(),
getNearestNeighbor_search_sorted());
}
int Settings::getHomographyMethod()

View File

@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Vocabulary.h"
#include <QtCore/QVector>
#include <stdio.h>
#include <opencv2/gpu/gpu.hpp>
namespace find_object {
@ -67,7 +68,7 @@ QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptors, int object
if(!indexedDescriptors_.empty() && indexedDescriptors_.rows >= (int)k)
{
Q_ASSERT(indexedDescriptors_.type() == descriptors.type() && indexedDescriptors_.cols == descriptors.cols);
flannIndex_.knnSearch(descriptors, results, dists, k, Settings::getFlannSearchParams() );
this->search(descriptors, results, dists, k);
if( dists.type() == CV_32S )
{
@ -207,7 +208,7 @@ void Vocabulary::update()
notIndexedWordIds_.clear();
}
if(!indexedDescriptors_.empty())
if(!indexedDescriptors_.empty() && !Settings::isBruteForceNearestNeighbor())
{
cv::flann::IndexParams * params = Settings::createFlannIndexParams();
flannIndex_.build(indexedDescriptors_, *params, Settings::getFlannDistanceType());
@ -223,7 +224,46 @@ void Vocabulary::search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat
{
Q_ASSERT(descriptors.type() == indexedDescriptors_.type() && descriptors.cols == indexedDescriptors_.cols);
flannIndex_.knnSearch(descriptors, results, dists, k, Settings::getFlannSearchParams());
if(Settings::isBruteForceNearestNeighbor())
{
std::vector<std::vector<cv::DMatch> > matches;
if(Settings::getNearestNeighbor_BruteForce_gpu() && cv::gpu::getCudaEnabledDeviceCount())
{
cv::gpu::GpuMat newDescriptorsGpu(descriptors);
cv::gpu::GpuMat lastDescriptorsGpu(indexedDescriptors_);
if(indexedDescriptors_.type()==CV_8U)
{
cv::gpu::BruteForceMatcher_GPU<cv::Hamming> gpuMatcher;
gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
}
else
{
cv::gpu::BruteForceMatcher_GPU<cv::L2<float> > gpuMatcher;
gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
}
}
else
{
cv::BFMatcher matcher(indexedDescriptors_.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2);
matcher.knnMatch(descriptors, indexedDescriptors_, matches, k);
}
//convert back to matrix style
results = cv::Mat(matches.size(), k, CV_32SC1);
dists = cv::Mat(matches.size(), k, CV_32FC1);
for(unsigned int i=0; i<matches.size(); ++i)
{
for(int j=0; j<k; ++j)
{
results.at<int>(i, j) = matches[i].at(j).trainIdx;
dists.at<float>(i, j) = matches[i].at(j).distance;
}
}
}
else
{
flannIndex_.knnSearch(descriptors, results, dists, k, Settings::getFlannSearchParams());
}
if( dists.type() == CV_32S )
{