1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Try to remove features dependency from 3d module.

This commit is contained in:
Alexander Smorkalov
2026-05-22 17:25:13 +03:00
parent fe94255a5f
commit d8d1cc8c58
4 changed files with 108 additions and 13 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ set(debug_modules "")
if(DEBUG_opencv_3d)
list(APPEND debug_modules opencv_highgui)
endif()
ocv_define_module(3d opencv_imgproc opencv_features opencv_flann ${debug_modules}
ocv_define_module(3d opencv_imgproc opencv_flann ${debug_modules}
WRAP java objc python js
)
ocv_target_link_libraries(${the_module} ${LAPACK_LIBRARIES})
-1
View File
@@ -64,7 +64,6 @@
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/hal/intrin.hpp"
+64 -1
View File
@@ -611,6 +611,69 @@ float Utils::findMedian (std::vector<float> &array) {
}
}
// Flann radiusMatch
struct FlannMatcher
{
Ptr<flann::IndexParams> indexParams;
Ptr<flann::SearchParams> searchParams;
Ptr<flann::Index> flannIndex;
FlannMatcher( const Ptr<flann::IndexParams>& _indexParams, const Ptr<flann::SearchParams>& _searchParams )
: indexParams(_indexParams), searchParams(_searchParams)
{
CV_Assert( _indexParams );
CV_Assert( _searchParams );
}
void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
std::vector<std::vector<DMatch> >& matches, float maxDistance)
{
CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() );
if( trainDescriptors.empty() || queryDescriptors.empty() )
return;
matches.clear();
flannIndex = makePtr<flann::Index>( trainDescriptors, *indexParams );
Mat indices( queryDescriptors.rows, 1, CV_32SC1, Scalar::all(-1) );
Mat dists( queryDescriptors.rows, 1, CV_32FC1, Scalar::all(-1) );
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{
Mat queryDescriptorsRow = queryDescriptors.row(qIdx);
Mat indicesRow = indices.row(qIdx);
Mat distsRow = dists.row(qIdx);
flannIndex->radiusSearch( queryDescriptorsRow, indicesRow, distsRow, maxDistance*maxDistance, 1, *searchParams );
}
convertToDMatches( indices, dists, matches );
}
void convertToDMatches( const Mat& indices, const Mat& dists, std::vector<std::vector<DMatch> >& matches )
{
matches.resize( indices.rows );
for( int i = 0; i < indices.rows; i++ )
{
for( int j = 0; j < indices.cols; j++ )
{
int idx = indices.at<int>(i, j);
if( idx >= 0 )
{
int imgIdx = 0;
int trainIdx = idx;
float dist = 0;
if (dists.type() == CV_32S)
dist = static_cast<float>( dists.at<int>(i,j) );
else
dist = std::sqrt(dists.at<float>(i,j));
matches[i].push_back( DMatch( i, trainIdx, imgIdx, dist ) );
}
}
}
}
};
///////////////////////////////// Radius Search Graph /////////////////////////////////////////////
class RadiusSearchNeighborhoodGraphImpl : public RadiusSearchNeighborhoodGraph {
private:
@@ -621,7 +684,7 @@ public:
// Radius search OpenCV works only with float data
CV_Assert(container_.type() == CV_32F);
FlannBasedMatcher flann(makePtr<flann::KDTreeIndexParams>(num_kd_trees), makePtr<flann::SearchParams>(flann_search_params));
FlannMatcher flann(makePtr<flann::KDTreeIndexParams>(num_kd_trees), makePtr<flann::SearchParams>(flann_search_params));
std::vector<std::vector<DMatch>> neighbours;
flann.radiusMatch(container_, container_, neighbours, (float)radius);
+43 -10
View File
@@ -42,7 +42,12 @@
//M*/
#include "test_precomp.hpp"
#include <opencv2/features.hpp>
// #define SAVE_FEATURES 1
#ifdef SAVE_FEATURES
# include "opencv2/features.hpp"
#endif
namespace opencv_test { namespace {
@@ -604,13 +609,39 @@ TEST(Calib3d_Homography, EKcase)
ASSERT_LE(err, 0.01);
}
#ifdef SAVE_FEATURES
static void saveKeypoints(const std::string& fname, const std::vector<cv::Point2f> points)
{
FileStorage fs(fname, cv::FileStorage::WRITE);
ASSERT_TRUE(fs.isOpened());
fs << "keypoints" << points;
fs.release();
}
#else
static void loadKeypoints(const std::string& fname, std::vector<cv::Point2f>& points)
{
FileStorage fs(fname, cv::FileStorage::READ);
ASSERT_TRUE(fs.isOpened());
fs["keypoints"] >> points;
fs.release();
}
#endif
TEST(Calib3d_Homography, fromImages)
{
const std::string points_file1 = cvtest::TS::ptr()->get_data_path() + "cv/optflow/image1.ORB.yaml.gz";
const std::string points_file2 = cvtest::TS::ptr()->get_data_path() + "cv/optflow/image2.ORB.yaml.gz";
std::vector<Point2f> pointframe1;
std::vector<Point2f> pointframe2;
#ifdef SAVE_FEATURES
vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
Mat img_1 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image1.png", 0);
Mat img_2 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image2.png", 0);
Ptr<ORB> orb = ORB::create();
vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
orb->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1, false );
orb->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2, false );
@@ -637,8 +668,6 @@ TEST(Calib3d_Homography, fromImages)
}
//-- Localize the model
std::vector<Point2f> pointframe1;
std::vector<Point2f> pointframe2;
for( int i = 0; i < (int)good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
@@ -646,6 +675,15 @@ TEST(Calib3d_Homography, fromImages)
pointframe2.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );
}
saveKeypoints(points_file1, pointframe1);
saveKeypoints(points_file2, pointframe2);
#else
loadKeypoints(points_file1, pointframe1);
loadKeypoints(points_file2, pointframe2);
#endif
ASSERT_FALSE(pointframe1.empty());
ASSERT_FALSE(pointframe1.empty());
Mat H0, H1, inliers0, inliers1;
double min_t0 = DBL_MAX, min_t1 = DBL_MAX;
for( int i = 0; i < 10; i++ )
@@ -664,11 +702,6 @@ TEST(Calib3d_Homography, fromImages)
min_t1 = std::min(min_t1, t);
}
int ninliers1 = countNonZero(inliers1);
double freq = getTickFrequency();
printf("nfeatures1 = %d, nfeatures2=%d, matches=%d, ninliers(RANSAC)=%d, "
"time(RANSAC)=%.2fmsec, ninliers(RHO)=%d, time(RHO)=%.2fmsec\n",
(int)keypoints_1.size(), (int)keypoints_2.size(),
(int)good_matches.size(), ninliers0, min_t0*1000./freq, ninliers1, min_t1*1000./freq);
ASSERT_TRUE(!H0.empty());
ASSERT_GE(ninliers0, 80);