added functionality to merge rois

This commit is contained in:
2026-08-05 18:32:25 +02:00
parent b10ac73e9b
commit 1fa04a8e8f
4 changed files with 157 additions and 1 deletions
+3 -1
View File
@@ -414,7 +414,8 @@ set(PUBLICHEADERS
include/aare/RawMasterFile.hpp
include/aare/RawSubFile.hpp
include/aare/VarClusterFinder.hpp
include/aare/utils/task.hpp)
include/aare/utils/task.hpp
include/aare/utils/utility_functions.hpp)
set(SourceFiles
${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.cpp
@@ -507,6 +508,7 @@ if(AARE_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/utility_functions.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp)
target_sources(tests PRIVATE ${TestSources})
endif()
+5
View File
@@ -186,6 +186,11 @@ struct ROI {
bool contains(ssize_t x, ssize_t y) const {
return x >= xmin && x < xmax && y >= ymin && y < ymax;
}
bool operator==(const ROI &other) const {
return xmin == other.xmin && xmax == other.xmax && ymin == other.ymin &&
ymax == other.ymax;
}
};
/// @brief Chip specifications for Matterhorn1
+92
View File
@@ -0,0 +1,92 @@
#pragma once
#include "aare/defs.hpp"
#include <algorithm>
#include <numeric>
#include <optional>
#include <vector>
namespace aare {
/**
* @brief Merge all consecutive ROIs in a vector into a single ROI.
* @param rois vector of ROIs to merge
* @return vector of merged ROIs
* @tparam horizontally_aligned true if the ROIs are horizontally aligned, false
* otherwise
* @tparam vertically_aligned true if the ROIs are vertically aligned, false
* otherwise
*/
template <bool horizontally_aligned = false, bool vertically_aligned = false>
std::vector<ROI> merge_consecutive_rois(std::vector<ROI> &rois) {
if constexpr (horizontally_aligned && vertically_aligned) {
throw std::runtime_error(
LOCATION + "Vector of the same ROI? Cannot merge ROIs both "
"horizontally and vertically at the same time.");
}
if (rois.empty()) {
return {};
}
if (rois.size() == 1) {
return rois;
}
auto merge_along_x = [](std::vector<ROI> in_rois) {
std::sort(in_rois.begin(), in_rois.end(),
[](const ROI &a, const ROI &b) {
return (a.ymin != b.ymin) ? (a.ymin < b.ymin)
: (a.xmin < b.xmin);
}); // N log (N)
std::vector<ROI> merged_rois;
merged_rois.reserve(in_rois.size());
merged_rois.push_back(in_rois[0]);
for (size_t i = 1; i < in_rois.size(); ++i) {
auto &last = merged_rois.back();
const auto &current = in_rois[i];
if (last.ymin == current.ymin && last.ymax == current.ymax &&
last.xmax == current.xmin) {
// merge
last.xmax = current.xmax;
} else {
merged_rois.push_back(current);
}
}
return merged_rois;
};
auto merge_along_y = [](std::vector<ROI> in_rois) {
std::sort(in_rois.begin(), in_rois.end(),
[](const ROI &a, const ROI &b) {
return (a.xmin != b.xmin) ? (a.xmin < b.xmin)
: (a.ymin < b.ymin);
});
std::vector<ROI> merged_rois;
merged_rois.reserve(in_rois.size());
merged_rois.push_back(in_rois[0]);
for (size_t i = 1; i < in_rois.size(); ++i) {
auto &last = merged_rois.back();
const auto &current = in_rois[i];
if (last.xmin == current.xmin && last.xmax == current.xmax &&
last.ymax == current.ymin) {
last.ymax = current.ymax;
} else {
merged_rois.push_back(current);
}
}
return merged_rois;
};
if constexpr (horizontally_aligned) {
return merge_along_y(rois); // one sort + one pass
} else if constexpr (vertically_aligned) {
return merge_along_x(rois); // one sort + one pass
} else {
return merge_along_y(merge_along_x(rois)); // generic case: two passes
}
}
} // namespace aare
+57
View File
@@ -0,0 +1,57 @@
#include "aare/utils/utility_functions.hpp"
#include <catch2/catch_test_macros.hpp>
namespace aare {
TEST_CASE("merge ROIs", "[utility_functions]") {
SECTION("not fully contiguous") {
std::vector<ROI> rois = {ROI{20, 30, 50, 60}, ROI{20, 30, 40, 50},
ROI{10, 20, 40, 50}};
auto merged_rois = merge_consecutive_rois<false, false>(rois);
REQUIRE(merged_rois.size() == 2);
REQUIRE(merged_rois[0] == ROI{10, 30, 40, 50});
REQUIRE(merged_rois[1] == ROI{20, 30, 50, 60});
}
SECTION("complex merge") {
std::vector<ROI> rois = {ROI{40, 50, 20, 30}, ROI{10, 20, 30, 40},
ROI{10, 20, 50, 60}, ROI{20, 30, 30, 40},
ROI{60, 70, 30, 40}, ROI{60, 70, 20, 30},
ROI{20, 30, 20, 30}, ROI{10, 20, 20, 30}};
auto merged_rois = merge_consecutive_rois<false, false>(rois);
REQUIRE(merged_rois.size() == 4);
REQUIRE(merged_rois[0] == ROI{10, 30, 20, 40});
REQUIRE(merged_rois[1] == ROI{10, 20, 50, 60});
REQUIRE(merged_rois[2] == ROI{40, 50, 20, 30});
REQUIRE(merged_rois[3] == ROI{60, 70, 20, 40});
}
SECTION("horizontally aligned") {
std::vector<ROI> rois = {ROI{10, 20, 30, 40}, ROI{10, 20, 50, 60},
ROI{10, 20, 20, 30}};
auto merged_rois = merge_consecutive_rois<true, false>(rois);
REQUIRE(merged_rois.size() == 2);
REQUIRE(merged_rois[0] == ROI{10, 20, 20, 40});
REQUIRE(merged_rois[1] == ROI{10, 20, 50, 60});
}
SECTION("vertically aligned") {
std::vector<ROI> rois = {ROI{10, 20, 30, 40}, ROI{30, 40, 30, 40},
ROI{20, 30, 30, 40}};
auto merged_rois = merge_consecutive_rois<false, true>(rois);
REQUIRE(merged_rois.size() == 1);
REQUIRE(merged_rois[0] == ROI{10, 40, 30, 40});
}
}
} // namespace aare