12 inline bool is_fg(
float v)
noexcept {
return v >= 0.5F; }
14 std::vector<float> morph_op(
15 std::span<const float> mask, uint32_t w, uint32_t
h,
16 uint32_t
radius,
bool dilating)
18 const size_t n =
static_cast<size_t>(w) *
h;
19 const auto r =
static_cast<int32_t
>(
radius);
20 std::vector<float> out(n);
22 P::for_each(P::par_unseq,
23 std::views::iota(
size_t { 0 }, n).begin(),
24 std::views::iota(
size_t { 0 }, n).end(),
26 const auto px =
static_cast<int32_t
>(idx % w);
27 const auto py =
static_cast<int32_t
>(idx / w);
29 bool result = !dilating;
31 for (int32_t dy = -r; dy <= r && result == !dilating; ++dy) {
32 const int32_t ny = std::clamp(py + dy, 0,
static_cast<int32_t
>(
h) - 1);
33 for (int32_t dx = -r; dx <= r && result == !dilating; ++dx) {
34 const int32_t nx = std::clamp(px + dx, 0,
static_cast<int32_t
>(w) - 1);
35 const bool fg = is_fg(mask[
static_cast<size_t>(ny) * w + nx]);
38 }
else if (!dilating && !fg) {
44 out[idx] = result ? 1.0F : 0.0F;
51 std::span<const float> mask, std::span<float> out,
52 uint32_t w, uint32_t
h, uint32_t
radius,
bool dilating)
54 const size_t n =
static_cast<size_t>(w) *
h;
55 const auto r =
static_cast<int32_t
>(
radius);
57 P::for_each(P::par_unseq,
58 std::views::iota(
size_t { 0 }, n).begin(),
59 std::views::iota(
size_t { 0 }, n).end(),
61 const auto px =
static_cast<int32_t
>(idx % w);
62 const auto py =
static_cast<int32_t
>(idx / w);
63 bool result = !dilating;
65 for (int32_t dy = -r; dy <= r && result == !dilating; ++dy) {
66 const int32_t ny = std::clamp(py + dy, 0,
static_cast<int32_t
>(
h) - 1);
68 for (int32_t dx = -r; dx <= r && result == !dilating; ++dx) {
69 const int32_t nx = std::clamp(px + dx, 0,
static_cast<int32_t
>(w) - 1);
70 const bool fg = is_fg(mask[
static_cast<size_t>(ny) * w + nx]);
74 }
else if (!dilating && !fg) {
79 out[idx] = result ? 1.0F : 0.0F;
85void erode(std::span<const float> mask, std::span<float> dst,
86 uint32_t w, uint32_t
h, uint32_t
radius)
88 morph_op_into(mask, dst, w,
h,
radius,
false);
91std::vector<float>
erode(std::span<const float> mask, uint32_t w, uint32_t
h, uint32_t
radius)
93 std::vector<float> out(
static_cast<size_t>(w) *
h);
98void dilate(std::span<const float> mask, std::span<float> dst,
99 uint32_t w, uint32_t
h, uint32_t
radius)
101 morph_op_into(mask, dst, w,
h,
radius,
true);
104std::vector<float>
dilate(std::span<const float> mask, uint32_t w, uint32_t
h, uint32_t
radius)
106 std::vector<float> out(
static_cast<size_t>(w) *
h);
111void open(std::span<const float> mask, std::span<float> tmp, std::span<float> dst,
112 uint32_t w, uint32_t
h, uint32_t
radius)
118std::vector<float>
open(std::span<const float> mask, uint32_t w, uint32_t
h, uint32_t
radius)
120 std::vector<float> tmp(
static_cast<size_t>(w) *
h);
121 std::vector<float> out(tmp.size());
126void close(std::span<const float> mask, std::span<float> tmp, std::span<float> dst,
127 uint32_t w, uint32_t
h, uint32_t
radius)
133std::vector<float>
close(std::span<const float> mask, uint32_t w, uint32_t
h, uint32_t
radius)
135 std::vector<float> tmp(
static_cast<size_t>(w) *
h);
136 std::vector<float> out(tmp.size());
141void morph_gradient(std::span<const float> mask, std::span<float> tmp, std::span<float> dst,
142 uint32_t w, uint32_t
h, uint32_t
radius)
144 const auto en =
static_cast<Eigen::Index
>(
static_cast<size_t>(w) *
h);
148 Eigen::Map<Eigen::ArrayXf>(dst.data(), en) = Eigen::Map<const Eigen::ArrayXf>(tmp.data(), en)
149 - Eigen::Map<const Eigen::ArrayXf>(dst.data(), en);
154 std::vector<float> tmp(
static_cast<size_t>(w) *
h);
155 std::vector<float> out(tmp.size());
Binary morphological operations on normalised float masks.
void erode(std::span< const float > mask, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Erosion writing into dst.
void close(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological closing writing into dst.
void dilate(std::span< const float > mask, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Dilation writing into dst.
void morph_gradient(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological gradient (dilate - erode) writing into dst.
void open(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological opening writing into dst.