From 5003452aa664144a9a79efbe3d6a310dccb2c1dd Mon Sep 17 00:00:00 2001 From: Vadim Benkevich Date: Sun, 3 May 2026 03:19:45 +0300 Subject: [PATCH 1/3] TODO 200x --- .../model_min_cut/min_cut_cgal_structs.cpp | 1 + .../mvs/model_min_cut/min_cut_cgal_structs.h | 2 ++ .../model_min_cut/min_cut_model_builder.cpp | 29 +++++++++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp index e3363529..bbff8e2c 100644 --- a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp @@ -8,6 +8,7 @@ cgal_point_t to_cgal_point(vector3d p) { return cgal_point_t(p[0], p[1], p[2]); vertex_info_t::vertex_info_t(unsigned int camera_id, const cv::Vec3b& color) : color(color) + , sentinel(false) { camera_ids.push_back(camera_id); } diff --git a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h index 9264d80f..7fdc22b4 100644 --- a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h +++ b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h @@ -11,9 +11,11 @@ struct vertex_info_t { std::vector camera_ids; cv::Vec3b color; size_t vertex_on_surface_id; + bool sentinel; vertex_info_t() : color(0, 0, 255) // red color, BGR convention (OpenCV compatible) + , sentinel(false) { } diff --git a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp index f5e84c3a..9c3de17c 100644 --- a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp @@ -58,7 +58,8 @@ void MinCutModelBuilder::appendToTriangulation( // проверяем насколько ближайшая точка далеко vector3d np = from_cgal_point(nearest_vertex->point()); // TODO 2001 appendToTriangulation(): реализуйте нормальную проверку объединять ли точку с уже добавленной ранее (с учетом r и MERGE_THRESHOLD_RADIUS_KOEF) - to_merge = false; + to_merge = cv::norm(np - p) < MERGE_THRESHOLD_RADIUS_KOEF * r; + // to_merge = false; } vertex_info_t p_info(camera_id, color); @@ -145,9 +146,11 @@ void MinCutModelBuilder::insertBoundingBoxVertices(vector3d& bb_min, vector3d& b p[d] = corners[(i / powOf3) % 3][d]; powOf3 *= 3; } - vertex_info_t bounding_box_corner_empty_info; + vertex_info_t bounding_box_corner_info; + bounding_box_corner_info.sentinel = true; + debug_bounding_box_points.push_back(p); - points_to_insert.push_back(std::make_pair(to_cgal_point(p), bounding_box_corner_empty_info)); + points_to_insert.push_back(std::make_pair(to_cgal_point(p), bounding_box_corner_info)); } proxy->triangulation.insert(points_to_insert.begin(), points_to_insert.end()); @@ -478,6 +481,16 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect // TODO 2002 добавьте проверку - не опирается ли треугольник на одну из фиктивных вершин (лежащих на гранях вспомогательного bounding box), можете для этого использовать bb_min и bb_max, или добавьте явный флаг в каждую вершину // иначе говоря сделайте так чтобы такие треугольники не добавлялись в результирующую модель эти большие красные треугольники + bool isSentinel = false; + for (int v_index = 1; v_index <= 3; ++v_index) { + auto vi = ci->vertex((i + v_index) % 4); + isSentinel |= vi->info().sentinel; + } + + if (isSentinel) { + continue; + } + for (int v_index = 1; v_index <= 3; ++v_index) { auto vi = ci->vertex((i + v_index) % 4); size_t& surface_vertex_id = vi->info().vertex_on_surface_id; @@ -490,6 +503,16 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect // TODO 2003 некоторые треугольники выглядят темными в результирующей модели, проблема уходит если выключить в MeshLab освещение (кнопка желтой лампочка - Light on/off) которое учитывает нормаль, которая строится с учетом // порядка вершин треугольника (по часовой стрелке или против) иначе говоря оказывается что порядок обхода вершин в треугольнике не всегда корректен подумайте чем это вызывано и поправьте (лучше всего это делать посматривая на // картинку 'Figure 44.1' в документации https://doc.cgal.org/latest/Triangulation_3/index.html ) + vector3d p0 = from_cgal_point(ci->vertex((i + 1) % 4)->point()); + vector3d p1 = from_cgal_point(ci->vertex((i + 2) % 4)->point()); + vector3d p2 = from_cgal_point(ci->vertex((i + 3) % 4)->point()); + + vector3d normal = cv::normalize(((p1 - p0).cross(p2 - p1))); + + vector3d p3 = from_cgal_point(ci->vertex(i)->point()); + if ((p3 - p0).dot(normal) > 0) { + std::swap(face[0], face[1]); + } mesh_faces.push_back(face); } From 4b147485023e47586bd39811065a529239b237af Mon Sep 17 00:00:00 2001 From: Vadim Benkevich Date: Mon, 18 May 2026 00:45:57 +0300 Subject: [PATCH 2/3] Add weight fade --- .../mvs/model_min_cut/min_cut_cgal_structs.cpp | 7 +++++++ .../mvs/model_min_cut/min_cut_cgal_structs.h | 3 +++ src/phg/mvs/model_min_cut/min_cut_defines.h | 3 +++ .../model_min_cut/min_cut_model_builder.cpp | 18 +++++++++++++++--- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp index bbff8e2c..ba0e8dac 100644 --- a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp @@ -33,4 +33,11 @@ void vertex_info_t::merge(const vertex_info_t& that) for (int i = 1; i < camera_ids.size(); ++i) { rassert(camera_ids[i - 1] < camera_ids[i], 23781274121024); } + + // Take the minimum defined radius + if (!radius.has_value()) { + radius = that.radius; + } else if (that.radius.has_value()) { + radius = std::min(*radius, *that.radius); + } } diff --git a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h index 7fdc22b4..f94ec91b 100644 --- a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h +++ b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.h @@ -7,10 +7,13 @@ #include #include +#include + struct vertex_info_t { std::vector camera_ids; cv::Vec3b color; size_t vertex_on_surface_id; + std::optional radius; bool sentinel; vertex_info_t() diff --git a/src/phg/mvs/model_min_cut/min_cut_defines.h b/src/phg/mvs/model_min_cut/min_cut_defines.h index 3572d0b8..ee81241d 100644 --- a/src/phg/mvs/model_min_cut/min_cut_defines.h +++ b/src/phg/mvs/model_min_cut/min_cut_defines.h @@ -2,3 +2,6 @@ #define LAMBDA_OUT 1.0 #define LAMBDA_IN 1.0 + +// Tolerance parameter for weight fading +#define SIGMA_FACTOR 3.0 diff --git a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp index 9c3de17c..24b163cb 100644 --- a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp @@ -63,6 +63,7 @@ void MinCutModelBuilder::appendToTriangulation( } vertex_info_t p_info(camera_id, color); + p_info.radius = r; if (to_merge) { nearest_vertex->info().merge(p_info); } else { @@ -322,6 +323,11 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect const vector3d point0 = from_cgal_point(vi->point()); const std::vector facets_around_point0 = fetchVertexBoundingFacets(proxy->triangulation, vi); + double sigma = 0.0; + if (vi->info().radius) { + sigma = SIGMA_FACTOR * *vi->info().radius; + } + for (unsigned int ci = 0; ci < vi->info().camera_ids.size(); ++ci) { // для каждой вершины триангуляции point0 и каждой камеры к которой эта точка имеет отношение (т.е. содержится где-то в карте глубины) @@ -344,9 +350,11 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect rassert(intersected_facet != cgal_facet_t(), 2378213120305); // это ячейка триангуляции лежащая под поверхностью (т.е. сразу за вершиной) - const cell_handle_t cell_after_point = intersected_facet.first; + // const cell_handle_t cell_after_point = intersected_facet.first; // добавляем пропускной способности из этой ячейки (из этого тетрагедрончика) к стоку - cell_after_point->info().t_capacity += LAMBDA_IN; + // cell_after_point->info().t_capacity += LAMBDA_IN; + const cell_handle_t sink_cell = proxy->triangulation.locate(to_cgal_point(point0 + sigma * ray_from_camera)); + sink_cell->info().t_capacity += LAMBDA_IN; } // шагаем от точки до камеры выставляя веса на треугольниках (они же ребра в графе) которые пересекаются по мере трассировки луча @@ -391,7 +399,11 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect prev_distance = distance_from_surface; // увеличиваем пропускную способность на треугольнике-ребре (в направлении от камеры к точке) - next_cell->info().facets_capacities[next_cell_facet_subindex] += LAMBDA_OUT; + double face_capacity = LAMBDA_OUT; + if (sigma != 0.0) { + face_capacity *= (1.0 - std::exp(-prev_distance * prev_distance / (2.0 * sigma * sigma))); + } + next_cell->info().facets_capacities[next_cell_facet_subindex] += face_capacity; if (cur_facets.size() == 0) { // если на будущее у нас нет кандидатов-треугольников, значит мы закончили наш путь и следующая ячейка содержит нашу камеру From f0ce3f5eed57a36356a7b925aea9c4b4120239a6 Mon Sep 17 00:00:00 2001 From: Vadim Benkevich Date: Sun, 31 May 2026 01:56:38 +0300 Subject: [PATCH 3/3] Calc average position and color --- src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp | 2 ++ src/phg/mvs/model_min_cut/min_cut_model_builder.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp index ba0e8dac..07475b9c 100644 --- a/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_cgal_structs.cpp @@ -34,6 +34,8 @@ void vertex_info_t::merge(const vertex_info_t& that) rassert(camera_ids[i - 1] < camera_ids[i], 23781274121024); } + color = 0.5 * (color + that.color); + // Take the minimum defined radius if (!radius.has_value()) { radius = that.radius; diff --git a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp index 24b163cb..85518eba 100644 --- a/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp +++ b/src/phg/mvs/model_min_cut/min_cut_model_builder.cpp @@ -66,6 +66,7 @@ void MinCutModelBuilder::appendToTriangulation( p_info.radius = r; if (to_merge) { nearest_vertex->info().merge(p_info); + proxy->triangulation.move(nearest_vertex, CGAL::midpoint(nearest_vertex->point(), to_cgal_point(p))); } else { points_to_insert.push_back(std::make_pair(to_cgal_point(p), p_info)); } @@ -572,8 +573,13 @@ void MinCutModelBuilder::buildMesh(std::vector& mesh_faces, std::vect // TODO 3500 Weak support: реализуйте идею из jancosek2011 - Multi-View Reconstruction Preserving Weakly-Supported Surfaces - https://compsciclub.ru/attachments/classes/file_XyLpDjLx/jancosek2011.pdf // TODO 4001 подвиньте вершины в среднюю координату среди всех точек которые в ней зачлись +// Считаю нечестное среднее (считаю среднее для двух точек при слиянии), но зато обновляю триангуляцию. Интересно насколько сильно это отличается от честного усреднения. +// Я бы предположил, что вряд ли это можно заметить. // TODO 4002 поэкспериментируйте со значением MERGE_THRESHOLD_RADIUS_KOEF, есть ли интересности? какое значение вы бы предложили использовать в условной финальной версии? +// Небольшое изменение порога (0.1 -> 0.5) резко снижает количество треугольников (84000->34000). По качеству модели сложно что-либо сказать (она выглядит плохо +// при любом значении :) ). А дальше даже увеличение в 100 раз не дает такого сильного выигрыша (34000->24000) // TODO 4003 добавьте усреднение цветов среди всех склеившихся вершин, приложите скриншот с/без усреднения +// Аналогично позициям осредняю цвет при каждом слиянии // TODO 5001 как в целом можно ускорить реализацию? есть ли идеи? попробуйте это сделать (и запишите какого ускорения получилось добиться, а так же изменился ли результат) // подсказки-идеи: