From 5bb31314a2b0bf0d14b050f72b6a0ab2ab77f53d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 Mar 2026 18:15:53 +0000 Subject: [PATCH 1/5] task done --- src/phg/sift/sift.cpp | 161 +++++++++++++++++++++++++++++++++++++++++- tests/test_sift.cpp | 2 +- 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/phg/sift/sift.cpp b/src/phg/sift/sift.cpp index 72047711..037be39f 100755 --- a/src/phg/sift/sift.cpp +++ b/src/phg/sift/sift.cpp @@ -112,12 +112,16 @@ std::vector phg::buildOctaves(const cv::Mat& img, const phg:: // // вычтем sigma0 чтобы размыть ровно до нужной суммарной сигмы // TODO sigma_layer = ... (вычитаем как в sigma base); // cv::GaussianBlur(oct.layers[0], oct.layers[i], cv::Size(), sigma_layer, sigma_layer); + double sigma_total = sigma0 * std::pow(2.0, (double)i / s); + double sigma_layer = std::sqrt(sigma_total * sigma_total - sigma0 * sigma0); + cv::GaussianBlur(oct.layers[0], oct.layers[i], cv::Size(), sigma_layer, sigma_layer); } // подготавливаем базовый слой для следующей октавы if (o + 1 < n_octaves) { // используется в opencv, формула для пересчета ключевых точек: pt_upscaled = 2^o * pt_downscaled // TODO cv::resize(даунскейлим текущий слой в два раза, без интерполяции, просто сабсепмлинг); + base = downsample2x(oct.layers[s]); // можно использовать и downsample2x_avg(oct.layers[s]), это позволяет потом заапскейлить слои обратно до оригинального разрешения без сдвига // но потребуется везде изменить формулу для пересчета ключевых точек: pt_upscaled = (pt_downscaled + 0.5) * 2^o - 0.5 @@ -139,6 +143,9 @@ std::vector phg::buildDoG(const std::vector phg::findScaleSpaceExtrema(const std::vector phg::findScaleSpaceExtrema(const std::vector(yi + 1, xi + 1) - cL.at(yi + 1, xi - 1) - cL.at(yi - 1, xi + 1) + cL.at(yi - 1, xi - 1)) * 0.25f; // float dxs = TODO; // float dys = TODO; + dxx = cL.at(yi, xi + 1) + cL.at(yi, xi - 1) - 2.f * resp_center; + dyy = cL.at(yi + 1, xi) + cL.at(yi - 1, xi) - 2.f * resp_center; + dss = nL.at(yi, xi) + pL.at(yi, xi) - 2.f * resp_center; + + dxy = (cL.at(yi + 1, xi + 1) - cL.at(yi + 1, xi - 1) - cL.at(yi - 1, xi + 1) + cL.at(yi - 1, xi - 1)) * 0.25f; + dxs = (nL.at(yi, xi + 1) - nL.at(yi, xi - 1) - pL.at(yi, xi + 1) + pL.at(yi, xi - 1)) * 0.25f; + dys = (nL.at(yi + 1, xi) - nL.at(yi - 1, xi) - pL.at(yi + 1, xi) + pL.at(yi - 1, xi)) * 0.25f; cv::Matx33f H(dxx, dxy, dxs, dxy, dyy, dys, dxs, dys, dss); @@ -288,6 +328,21 @@ std::vector phg::findScaleSpaceExtrema(const std::vector (r + 1.f) * (r + 1.f) / r) + break; } // скейлим координаты точек обратно до родных размеров картинки @@ -412,6 +467,37 @@ std::vector phg::computeOrientations(const std::vector(py, px + 1) - img.at(py, px - 1); + float gy = img.at(py + 1, px) - img.at(py - 1, px); + + float mag = std::sqrt(gx * gx + gy * gy); + float angle = std::atan2(gy, gx); + + float angle_deg = angle * 180.f / (float)CV_PI; + if (angle_deg < 0.f) + angle_deg += 360.f; + + float weight = std::exp(-(dx * dx + dy * dy) / (2.f * sigma_win * sigma_win)); + if (!params.enable_orientation_gaussian_weighting) { + weight = 1.f; + } + + float bin = angle_deg * n_bins / 360.f; + if (bin >= n_bins) + bin -= n_bins; + int bin0 = (int)bin; + int bin1 = (bin0 + 1) % n_bins; + + float frac = bin - bin0; + if (!params.enable_orientation_bin_interpolation) { + frac = 0.f; + } + + histogram[bin0] += mag * weight * (1.f - frac); + histogram[bin1] += mag * weight * frac; } } @@ -464,6 +550,26 @@ std::vector phg::computeOrientations(const std::vector 1e-7f) { + offset = 0.5f * (left - right) / denom; + } + if (!params.enable_orientation_subpixel_localization) { + offset = 0.f; + } + + float bin_real = i + offset; + if (bin_real < 0.f) + bin_real += n_bins; + if (bin_real >= n_bins) + bin_real -= n_bins; + + float angle = bin_real * 360.f / n_bins; + + cv::KeyPoint new_kp = kp; + new_kp.angle = angle; + oriented_kpts.push_back(new_kp); } } } @@ -579,6 +685,11 @@ std::pair> phg::computeDescriptors(const std: // weight = 1.f; // } // float weighted_mag = mag * weight; + float weight = std::exp(-(rot_x * rot_x + rot_y * rot_y) / (2.f * sigma_desc * sigma_desc)); + if (!params.enable_descriptor_gaussian_weighting) { + weight = 1.f; + } + float weighted_mag = mag * weight; if (params.enable_descriptor_bin_interpolation) { // размажем вклад weighted_mag по пространственным бинам и по бинам гистограммок трилинейной интерполяцией @@ -611,6 +722,8 @@ std::pair> phg::computeDescriptors(const std: // int idx = TODO; // desc[idx] += TODO; + int idx = (iy * n_spatial_bins + ix) * n_orient_bins + io; + desc[idx] += weighted_mag * wx * wy * wo; } } } @@ -621,8 +734,8 @@ std::pair> phg::computeDescriptors(const std: if (ix_nearest >= 0 && ix_nearest < n_spatial_bins && iy_nearest >= 0 && iy_nearest < n_spatial_bins) { // TODO uncomment -// int idx = (iy_nearest * n_spatial_bins + ix_nearest) * n_orient_bins + io_nearest; -// desc[idx] += weighted_mag; + int idx = (iy_nearest * n_spatial_bins + ix_nearest) * n_orient_bins + io_nearest; + desc[idx] += weighted_mag; } } } @@ -720,7 +833,14 @@ void phg::SIFT::detectAndCompute(const cv::Mat& img, const cv::Mat& mask, std::v kpts = computeOrientations(kpts, octaves, p, verbose_level); // после подсчета ориентаций количество могло возрасти (и скорее всего возросло) // нужно снова выбрать лучшие точки чтобы уложиться в бюджет - kpts = selectTopKeypoints(kpts, p, verbose_level); + std::vector oriented_kpts = kpts; + int descriptor_budget = (int)oriented_kpts.size(); + if (p.nfeatures > 0) { + descriptor_budget = std::min((int)oriented_kpts.size(), std::max(p.nfeatures, (int)std::ceil(p.nfeatures * 1.5))); + SIFTParams descriptor_params = p; + descriptor_params.nfeatures = descriptor_budget; + kpts = selectTopKeypoints(oriented_kpts, descriptor_params, verbose_level); + } if (verbose_level >= 2) { cv::Mat kpts_img; @@ -732,6 +852,41 @@ void phg::SIFT::detectAndCompute(const cv::Mat& img, const cv::Mat& mask, std::v // TODO всегда ли мы получаем ровно столько точек сколько запросили в параметре nfeatures? в каких случаях это не так и в какую сторону? // как подкрутить алгоритм, чтобы всегда выдавать ровно запрошенное количество точек (когда это в принципе возможно) но не сильно просесть в производительности? + while (p.nfeatures > 0 && (int)kpts.size() < p.nfeatures && descriptor_budget < (int)oriented_kpts.size()) { + int next_budget = std::min((int)oriented_kpts.size(), std::max(descriptor_budget + 1, descriptor_budget * 2)); + SIFTParams descriptor_params = p; + descriptor_params.nfeatures = next_budget; + std::vector candidate_kpts = selectTopKeypoints(oriented_kpts, descriptor_params, verbose_level); + std::tie(desc, kpts) = computeDescriptors(candidate_kpts, octaves, p, verbose_level); + descriptor_budget = next_budget; + } + + if (p.nfeatures > 0 && (int)kpts.size() > p.nfeatures) { + int nfeatures = p.nfeatures; + + std::vector idx(kpts.size()); + std::iota(idx.begin(), idx.end(), 0); + std::partial_sort(idx.begin(), idx.begin() + nfeatures, idx.end(), [&kpts](int a, int b) { return std::abs(kpts[a].response) > std::abs(kpts[b].response); }); + idx.resize(nfeatures); + std::sort(idx.begin(), idx.end()); + + std::vector sel_kpts; + sel_kpts.reserve(nfeatures); + cv::Mat sel_desc; + if (!desc.empty()) { + sel_desc.create(0, desc.cols, desc.type()); + } + + for (int i : idx) { + sel_kpts.push_back(kpts[i]); + if (!desc.empty()) { + sel_desc.push_back(desc.row(i)); + } + } + + kpts = std::move(sel_kpts); + desc = std::move(sel_desc); + } } void phg::SIFT::saveImg(const std::string& name, const cv::Mat& img) const diff --git a/tests/test_sift.cpp b/tests/test_sift.cpp index cf3bd7df..7433f9bb 100755 --- a/tests/test_sift.cpp +++ b/tests/test_sift.cpp @@ -28,7 +28,7 @@ // TODO ENABLE ME // TODO ENABLE ME // TODO ENABLE ME -#define ENABLE_MY_SIFT_TESTING 0 +#define ENABLE_MY_SIFT_TESTING 1 #define DENY_CREATE_REF_DATA 1 From 24b19cb8556236fa96f5223535b8033ffd56f6ae Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Mar 2026 19:40:45 +0000 Subject: [PATCH 2/5] task done final --- src/phg/matching/descriptor_matcher.cpp | 79 +++++++++++++++- src/phg/matching/flann_matcher.cpp | 44 ++++++++- src/phg/sfm/homography.cpp | 120 +++++++++++++----------- src/phg/sfm/panorama_stitcher.cpp | 40 +++++++- tests/test_matching.cpp | 2 +- 5 files changed, 225 insertions(+), 60 deletions(-) diff --git a/src/phg/matching/descriptor_matcher.cpp b/src/phg/matching/descriptor_matcher.cpp index f4bcd871..f3c1881f 100644 --- a/src/phg/matching/descriptor_matcher.cpp +++ b/src/phg/matching/descriptor_matcher.cpp @@ -1,5 +1,8 @@ #include "descriptor_matcher.h" +#include +#include + #include #include "flann_factory.h" @@ -7,8 +10,22 @@ void phg::DescriptorMatcher::filterMatchesRatioTest(const std::vector &filtered_matches) { filtered_matches.clear(); + filtered_matches.reserve(matches.size()); + + const float ratio = 0.75f; + + for (const std::vector& knn_matches : matches) { + if (knn_matches.size() < 2) { + continue; + } - throw std::runtime_error("not implemented yet"); + const cv::DMatch& best = knn_matches[0]; + const cv::DMatch& second_best = knn_matches[1]; + + if (best.distance < ratio * second_best.distance) { + filtered_matches.push_back(best); + } + } } @@ -35,6 +52,7 @@ void phg::DescriptorMatcher::filterMatchesClusters(const std::vector points_query.at(i) = keypoints_query[matches[i].queryIdx].pt; points_train.at(i) = keypoints_train[matches[i].trainIdx].pt; } + // // // размерность всего 2, так что точное KD-дерево // std::shared_ptr index_params = flannKdTreeIndexParams(TODO); @@ -73,4 +91,63 @@ void phg::DescriptorMatcher::filterMatchesClusters(const std::vector // // метч остается, если левое и правое множества первых total_neighbors соседей в радиусах поиска(radius2_query, radius2_train) имеют как минимум consistent_matches общих элементов // // TODO заполнить filtered_matches + + std::shared_ptr index_params = flannKdTreeIndexParams(1); + std::shared_ptr search_params = flannKsTreeSearchParams(64); + + std::shared_ptr index_query = flannKdTreeIndex(points_query, index_params); + std::shared_ptr index_train = flannKdTreeIndex(points_train, index_params); + + cv::Mat indices_query(n_matches, total_neighbours, CV_32SC1); + cv::Mat distances2_query(n_matches, total_neighbours, CV_32FC1); + cv::Mat indices_train(n_matches, total_neighbours, CV_32SC1); + cv::Mat distances2_train(n_matches, total_neighbours, CV_32FC1); + + index_query->knnSearch(points_query, indices_query, distances2_query, (int)total_neighbours, *search_params); + index_train->knnSearch(points_train, indices_train, distances2_train, (int)total_neighbours, *search_params); + + float radius2_query, radius2_train; + { + std::vector max_dists2_query(n_matches); + std::vector max_dists2_train(n_matches); + for (int i = 0; i < n_matches; ++i) { + max_dists2_query[i] = distances2_query.at(i, (int)total_neighbours - 1); + max_dists2_train[i] = distances2_train.at(i, (int)total_neighbours - 1); + } + + int median_pos = n_matches / 2; + std::nth_element(max_dists2_query.begin(), max_dists2_query.begin() + median_pos, max_dists2_query.end()); + std::nth_element(max_dists2_train.begin(), max_dists2_train.begin() + median_pos, max_dists2_train.end()); + + radius2_query = max_dists2_query[median_pos] * radius_limit_scale * radius_limit_scale; + radius2_train = max_dists2_train[median_pos] * radius_limit_scale * radius_limit_scale; + } + + filtered_matches.reserve(matches.size()); + + std::vector neighbour_in_query(n_matches, 0); + for (int i = 0; i < n_matches; ++i) { + std::fill(neighbour_in_query.begin(), neighbour_in_query.end(), 0); + + for (size_t j = 0; j < total_neighbours; ++j) { + int idx = indices_query.at(i, (int)j); + float dist2 = distances2_query.at(i, (int)j); + if (idx >= 0 && dist2 <= radius2_query) { + neighbour_in_query[idx] = 1; + } + } + + int consistent_count = 0; + for (size_t j = 0; j < total_neighbours; ++j) { + int idx = indices_train.at(i, (int)j); + float dist2 = distances2_train.at(i, (int)j); + if (idx >= 0 && dist2 <= radius2_train && neighbour_in_query[idx]) { + ++consistent_count; + } + } + + if (consistent_count >= (int)consistent_matches) { + filtered_matches.push_back(matches[i]); + } + } } diff --git a/src/phg/matching/flann_matcher.cpp b/src/phg/matching/flann_matcher.cpp index 9e9f5180..f4a60b86 100644 --- a/src/phg/matching/flann_matcher.cpp +++ b/src/phg/matching/flann_matcher.cpp @@ -1,4 +1,5 @@ #include +#include #include "flann_matcher.h" #include "flann_factory.h" @@ -6,16 +7,53 @@ phg::FlannMatcher::FlannMatcher() { // параметры для приближенного поиска -// index_params = flannKdTreeIndexParams(TODO); -// search_params = flannKsTreeSearchParams(TODO); + index_params = flannKdTreeIndexParams(4); + search_params = flannKsTreeSearchParams(32); } void phg::FlannMatcher::train(const cv::Mat &train_desc) { + if (train_desc.rows >= 2000) { + index_params = flannKdTreeIndexParams(4); + search_params = flannKsTreeSearchParams(32); + } else { + index_params = flannKdTreeIndexParams(1); + search_params = flannKsTreeSearchParams(16); + } + flann_index = flannKdTreeIndex(train_desc, index_params); } void phg::FlannMatcher::knnMatch(const cv::Mat &query_desc, std::vector> &matches, int k) const { - throw std::runtime_error("not implemented yet"); + matches.clear(); + matches.resize(query_desc.rows); + + if (query_desc.rows == 0) { + return; + } + + cv::Mat indices(query_desc.rows, k, CV_32SC1); + cv::Mat distances(query_desc.rows, k, CV_32FC1); + flann_index->knnSearch(query_desc, indices, distances, k, *search_params); + + for (int qi = 0; qi < query_desc.rows; ++qi) { + std::vector& dst = matches[qi]; + dst.clear(); + dst.reserve(k); + + for (int j = 0; j < k; ++j) { + int train_idx = indices.at(qi, j); + if (train_idx < 0) { + continue; + } + + cv::DMatch match; + match.distance = std::sqrt(distances.at(qi, j)); + match.imgIdx = 0; + match.queryIdx = qi; + match.trainIdx = train_idx; + dst.push_back(match); + } + } } diff --git a/src/phg/sfm/homography.cpp b/src/phg/sfm/homography.cpp index 5cbc780c..95bb39e6 100644 --- a/src/phg/sfm/homography.cpp +++ b/src/phg/sfm/homography.cpp @@ -64,6 +64,7 @@ namespace { { std::vector> A; std::vector H; + A.reserve(8); double xs0[4] = {l0.x, l1.x, l2.x, l3.x}; double xs1[4] = {r0.x, r1.x, r2.x, r3.x}; @@ -84,8 +85,9 @@ namespace { double w1 = ws1[i]; // 8 elements of matrix + free term as needed by gauss routine -// A.push_back({TODO}); -// A.push_back({TODO}); + (void)w1; + A.push_back({x0, y0, w0, 0.0, 0.0, 0.0, -x0 * x1, -y0 * x1, x1 * w0}); + A.push_back({0.0, 0.0, 0.0, x0, y0, w0, -x0 * y1, -y0 * y1, y1 * w0}); } int res = gauss(A, H); @@ -168,57 +170,60 @@ namespace { // * (простое описание для понимания) // * [3] http://ikrisoft.blogspot.com/2015/01/ransac-with-contrario-approach.html -// const int n_matches = points_lhs.size(); -// -// // https://en.wikipedia.org/wiki/Random_sample_consensus#Parameters -// const int n_trials = TODO; -// -// const int n_samples = TODO; -// uint64_t seed = 1; -// const double reprojection_error_threshold_px = 2; -// -// int best_support = 0; -// cv::Mat best_H; -// -// std::vector sample; -// for (int i_trial = 0; i_trial < n_trials; ++i_trial) { -// randomSample(sample, n_matches, n_samples, &seed); -// -// cv::Mat H = estimateHomography4Points(points_lhs[sample[0]], points_lhs[sample[1]], points_lhs[sample[2]], points_lhs[sample[3]], -// points_rhs[sample[0]], points_rhs[sample[1]], points_rhs[sample[2]], points_rhs[sample[3]]); -// -// int support = 0; -// for (int i_point = 0; i_point < n_matches; ++i_point) { -// try { -// cv::Point2d proj = phg::transformPoint(points_lhs[i_point], H); -// if (cv::norm(proj - cv::Point2d(points_rhs[i_point])) < reprojection_error_threshold_px) { -// ++support; -// } -// } catch (const std::exception &e) -// { -// std::cerr << e.what() << std::endl; -// } -// } -// -// if (support > best_support) { -// best_support = support; -// best_H = H; -// -// std::cout << "estimateHomographyRANSAC : support: " << best_support << "/" << n_matches << std::endl; -// -// if (best_support == n_matches) { -// break; -// } -// } -// } -// -// std::cout << "estimateHomographyRANSAC : best support: " << best_support << "/" << n_matches << std::endl; -// -// if (best_support == 0) { -// throw std::runtime_error("estimateHomographyRANSAC : failed to estimate homography"); -// } -// -// return best_H; + const int n_matches = points_lhs.size(); + + // https://en.wikipedia.org/wiki/Random_sample_consensus#Parameters + const int n_trials = 1000; + + const int n_samples = 4; + uint64_t seed = 1; + const double reprojection_error_threshold_px = 2.0; + + int best_support = 0; + cv::Mat best_H; + + std::vector sample; + for (int i_trial = 0; i_trial < n_trials; ++i_trial) { + randomSample(sample, n_matches, n_samples, &seed); + + cv::Mat H; + try { + H = estimateHomography4Points(points_lhs[sample[0]], points_lhs[sample[1]], points_lhs[sample[2]], points_lhs[sample[3]], + points_rhs[sample[0]], points_rhs[sample[1]], points_rhs[sample[2]], points_rhs[sample[3]]); + } catch (const std::exception &) { + continue; + } + + int support = 0; + for (int i_point = 0; i_point < n_matches; ++i_point) { + try { + cv::Point2d proj = phg::transformPoint(points_lhs[i_point], H); + if (cv::norm(proj - cv::Point2d(points_rhs[i_point])) < reprojection_error_threshold_px) { + ++support; + } + } catch (const std::exception &) { + } + } + + if (support > best_support) { + best_support = support; + best_H = H; + + std::cout << "estimateHomographyRANSAC : support: " << best_support << "/" << n_matches << std::endl; + + if (best_support == n_matches) { + break; + } + } + } + + std::cout << "estimateHomographyRANSAC : best support: " << best_support << "/" << n_matches << std::endl; + + if (best_support == 0) { + throw std::runtime_error("estimateHomographyRANSAC : failed to estimate homography"); + } + + return best_H; } } @@ -238,7 +243,14 @@ cv::Mat phg::findHomographyCV(const std::vector &points_lhs, const // таким преобразованием внутри занимается функции cv::perspectiveTransform и cv::warpPerspective cv::Point2d phg::transformPoint(const cv::Point2d &pt, const cv::Mat &T) { - throw std::runtime_error("not implemented yet"); + double x = pt.x; + double y = pt.y; + + double tx = T.at(0, 0) * x + T.at(0, 1) * y + T.at(0, 2); + double ty = T.at(1, 0) * x + T.at(1, 1) * y + T.at(1, 2); + double tw = T.at(2, 0) * x + T.at(2, 1) * y + T.at(2, 2); + + return cv::Point2d(tx / tw, ty / tw); } cv::Point2d phg::transformPointCV(const cv::Point2d &pt, const cv::Mat &T) { diff --git a/src/phg/sfm/panorama_stitcher.cpp b/src/phg/sfm/panorama_stitcher.cpp index 8d76939b..3267f45b 100644 --- a/src/phg/sfm/panorama_stitcher.cpp +++ b/src/phg/sfm/panorama_stitcher.cpp @@ -3,6 +3,7 @@ #include #include +#include /* * imgs - список картинок @@ -23,7 +24,44 @@ cv::Mat phg::stitchPanorama(const std::vector &imgs, { // здесь надо посчитать вектор Hs // при этом можно обойтись n_images - 1 вызовами функтора homography_builder - throw std::runtime_error("not implemented yet"); + std::vector edge_H(n_images); + std::vector edge_ready(n_images, 0); + std::vector H_ready(n_images, 0); + + for (int i = 0; i < n_images; ++i) { + if (parent[i] == -1) { + Hs[i] = cv::Mat::eye(3, 3, CV_64FC1); + H_ready[i] = 1; + } + } + + for (int i = 0; i < n_images; ++i) { + if (H_ready[i]) { + continue; + } + + std::vector chain; + int cur = i; + while (!H_ready[cur]) { + chain.push_back(cur); + + int p = parent[cur]; + + if (!edge_ready[cur]) { + edge_H[cur] = homography_builder(imgs[cur], imgs[p]); + edge_ready[cur] = 1; + } + + cur = p; + } + + for (int k = (int)chain.size() - 1; k >= 0; --k) { + int v = chain[k]; + int p = parent[v]; + Hs[v] = Hs[p] * edge_H[v]; + H_ready[v] = 1; + } + } } bbox2 bbox; diff --git a/tests/test_matching.cpp b/tests/test_matching.cpp index adaac65e..c9e927e1 100644 --- a/tests/test_matching.cpp +++ b/tests/test_matching.cpp @@ -20,7 +20,7 @@ // TODO enable both toggles for testing custom detector & matcher #define ENABLE_MY_DESCRIPTOR 0 -#define ENABLE_MY_MATCHING 0 +#define ENABLE_MY_MATCHING 1 #define ENABLE_GPU_BRUTEFORCE_MATCHER 0 // TODO disable for local testing but do not commit From f78aaac5d05bb0266f36fca499aa31d3e9929d58 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Mar 2026 20:05:14 +0000 Subject: [PATCH 3/5] fix windows tests --- src/phg/matching/flann_matcher.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/phg/matching/flann_matcher.cpp b/src/phg/matching/flann_matcher.cpp index f4a60b86..d8874371 100644 --- a/src/phg/matching/flann_matcher.cpp +++ b/src/phg/matching/flann_matcher.cpp @@ -13,13 +13,8 @@ phg::FlannMatcher::FlannMatcher() void phg::FlannMatcher::train(const cv::Mat &train_desc) { - if (train_desc.rows >= 2000) { - index_params = flannKdTreeIndexParams(4); - search_params = flannKsTreeSearchParams(32); - } else { - index_params = flannKdTreeIndexParams(1); - search_params = flannKsTreeSearchParams(16); - } + index_params = flannKdTreeIndexParams(4); + search_params = flannKsTreeSearchParams(32); flann_index = flannKdTreeIndex(train_desc, index_params); } From 789cf7e115a47d9427639e87b22a8d85681af287 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Mar 2026 20:31:14 +0000 Subject: [PATCH 4/5] fix tests again --- src/phg/matching/descriptor_matcher.cpp | 6 +++--- src/phg/matching/flann_matcher.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/phg/matching/descriptor_matcher.cpp b/src/phg/matching/descriptor_matcher.cpp index f3c1881f..e47d0560 100644 --- a/src/phg/matching/descriptor_matcher.cpp +++ b/src/phg/matching/descriptor_matcher.cpp @@ -12,7 +12,7 @@ void phg::DescriptorMatcher::filterMatchesRatioTest(const std::vector& knn_matches : matches) { if (knn_matches.size() < 2) { @@ -22,7 +22,7 @@ void phg::DescriptorMatcher::filterMatchesRatioTest(const std::vector // // TODO заполнить filtered_matches std::shared_ptr index_params = flannKdTreeIndexParams(1); - std::shared_ptr search_params = flannKsTreeSearchParams(64); + std::shared_ptr search_params = flannKsTreeSearchParams(32); std::shared_ptr index_query = flannKdTreeIndex(points_query, index_params); std::shared_ptr index_train = flannKdTreeIndex(points_train, index_params); diff --git a/src/phg/matching/flann_matcher.cpp b/src/phg/matching/flann_matcher.cpp index d8874371..ecc51f64 100644 --- a/src/phg/matching/flann_matcher.cpp +++ b/src/phg/matching/flann_matcher.cpp @@ -28,9 +28,9 @@ void phg::FlannMatcher::knnMatch(const cv::Mat &query_desc, std::vectorknnSearch(query_desc, indices, distances, k, *search_params); + cv::Mat indices; + cv::Mat distances; + flann_index->knnSearch(query_desc, indices, distances, k); for (int qi = 0; qi < query_desc.rows; ++qi) { std::vector& dst = matches[qi]; From 4dec6ddfa2d52d81a5e74088f715d77fd1c526a7 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Mar 2026 20:47:22 +0000 Subject: [PATCH 5/5] ubuntu back --- src/phg/matching/descriptor_matcher.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/phg/matching/descriptor_matcher.cpp b/src/phg/matching/descriptor_matcher.cpp index e47d0560..f3c1881f 100644 --- a/src/phg/matching/descriptor_matcher.cpp +++ b/src/phg/matching/descriptor_matcher.cpp @@ -12,7 +12,7 @@ void phg::DescriptorMatcher::filterMatchesRatioTest(const std::vector& knn_matches : matches) { if (knn_matches.size() < 2) { @@ -22,7 +22,7 @@ void phg::DescriptorMatcher::filterMatchesRatioTest(const std::vector // // TODO заполнить filtered_matches std::shared_ptr index_params = flannKdTreeIndexParams(1); - std::shared_ptr search_params = flannKsTreeSearchParams(32); + std::shared_ptr search_params = flannKsTreeSearchParams(64); std::shared_ptr index_query = flannKdTreeIndex(points_query, index_params); std::shared_ptr index_train = flannKdTreeIndex(points_train, index_params);