Skip to content

Commit e618fbf

Browse files
committed
Use linear interpolation for match_histogram to smooth result. Add equalize example and match_histogram unit tests
1 parent 97e68b6 commit e618fbf

5 files changed

Lines changed: 179 additions & 2 deletions

File tree

HighMap/src/filters/filters.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,20 @@ void match_histogram(Array &array, const Array &array_reference)
415415
std::vector<size_t> ki = argsort(array.vector);
416416
std::vector<size_t> kr = argsort(array_reference.vector);
417417

418-
for (size_t i = 0; i < ki.size(); i++)
419-
array.vector[ki[i]] = array_reference.vector[kr[i]];
418+
size_t n = ki.size();
419+
size_t nr = kr.size();
420+
421+
for (size_t i = 0; i < n; i++)
422+
{
423+
// map rank i in source → fractional rank in reference
424+
float t = static_cast<float>(i) / (n - 1) * (nr - 1);
425+
size_t j0 = static_cast<size_t>(t);
426+
size_t j1 = std::min(j0 + 1, nr - 1);
427+
float f = t - static_cast<float>(j0);
428+
429+
array.vector[ki[i]] = (1.f - f) * array_reference.vector[kr[j0]] +
430+
f * array_reference.vector[kr[j1]];
431+
}
420432
}
421433

422434
Array mean_shift(const Array &array,

docs/images/ex_equalize.png

103 KB
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
add_executable(ex_equalize ex_equalize.cpp)
2+
target_link_libraries(ex_equalize highmap)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "highmap.hpp"
2+
3+
int main(void)
4+
{
5+
glm::ivec2 shape = {256, 256};
6+
glm::vec2 kw = {4.f, 4.f};
7+
int seed = 1;
8+
9+
hmap::Array z0 = hmap::noise_fbm(hmap::NoiseType::PERLIN, shape, kw, seed);
10+
hmap::clamp_min(z0, 0.f);
11+
12+
auto z1 = z0;
13+
hmap::equalize(z1);
14+
15+
hmap::export_banner_png("ex_equalize.png", {z0, z1}, hmap::Cmap::INFERNO);
16+
}

tests/src/test_math_histogram.cpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#include <gtest/gtest.h>
2+
3+
#include "highmap/array.hpp"
4+
#include "highmap/dbg/assert.hpp"
5+
#include "highmap/filters.hpp"
6+
#include "highmap/primitives.hpp"
7+
8+
using namespace hmap;
9+
10+
TEST(MatchHistogram, Identity)
11+
{
12+
Array input{
13+
{0.f, 1.f},
14+
{2.f, 3.f},
15+
};
16+
17+
Array reference = input;
18+
Array expected = input;
19+
20+
match_histogram(input, reference);
21+
22+
bool ret = assert_almost_equal(input, expected, 1e-6f);
23+
EXPECT_TRUE(ret);
24+
}
25+
26+
TEST(MatchHistogram, ConstantReference)
27+
{
28+
Array input{
29+
{0.f, 1.f},
30+
{2.f, 3.f},
31+
};
32+
33+
Array reference{
34+
{5.f, 5.f},
35+
{5.f, 5.f},
36+
};
37+
38+
Array expected{
39+
{5.f, 5.f},
40+
{5.f, 5.f},
41+
};
42+
43+
match_histogram(input, reference);
44+
45+
bool ret = assert_almost_equal(input, expected, 1e-6f);
46+
EXPECT_TRUE(ret);
47+
}
48+
49+
TEST(MatchHistogram, SortedRanks)
50+
{
51+
Array input{
52+
{0.f, 1.f},
53+
{2.f, 3.f},
54+
};
55+
56+
Array reference{
57+
{10.f, 20.f},
58+
{30.f, 40.f},
59+
};
60+
61+
Array expected{
62+
{10.f, 20.f},
63+
{30.f, 40.f},
64+
};
65+
66+
match_histogram(input, reference);
67+
68+
bool ret = assert_almost_equal(input, expected, 1e-6f);
69+
EXPECT_TRUE(ret);
70+
}
71+
72+
TEST(MatchHistogram, ReverseOrdering)
73+
{
74+
Array input{
75+
{3.f, 2.f},
76+
{1.f, 0.f},
77+
};
78+
79+
Array reference{
80+
{10.f, 20.f},
81+
{30.f, 40.f},
82+
};
83+
84+
Array expected{
85+
{40.f, 30.f},
86+
{20.f, 10.f},
87+
};
88+
89+
match_histogram(input, reference);
90+
91+
bool ret = assert_almost_equal(input, expected, 1e-6f);
92+
EXPECT_TRUE(ret);
93+
}
94+
95+
TEST(MatchHistogram, Interpolation)
96+
{
97+
Array input{
98+
{0.f, 1.f, 2.f},
99+
};
100+
101+
Array reference{
102+
{0.f, 10.f},
103+
};
104+
105+
Array expected{
106+
{0.f, 5.f, 10.f},
107+
};
108+
109+
match_histogram(input, reference);
110+
111+
bool ret = assert_almost_equal(input, expected, 1e-5f);
112+
EXPECT_TRUE(ret);
113+
}
114+
115+
TEST(MatchHistogram, RandomMonotonicity)
116+
{
117+
Array input = white({32, 32}, 0.f, 1.f, 42);
118+
Array reference = white({32, 32}, 10.f, 20.f, 123);
119+
120+
match_histogram(input, reference);
121+
122+
float vmin = input.min();
123+
float vmax = input.max();
124+
125+
EXPECT_GE(vmin, 10.f - 1e-4f);
126+
EXPECT_LE(vmax, 20.f + 1e-4f);
127+
}
128+
129+
TEST(MatchHistogram, SingleValueInput)
130+
{
131+
Array input{
132+
{42.f},
133+
};
134+
135+
Array reference{
136+
{7.f},
137+
};
138+
139+
Array expected{
140+
{7.f},
141+
};
142+
143+
match_histogram(input, reference);
144+
145+
bool ret = assert_almost_equal(input, expected, 1e-6f);
146+
EXPECT_TRUE(ret);
147+
}

0 commit comments

Comments
 (0)