### Moved rect2d impl in its own file and use periodic line decomp.

parent 464b7d0b
 ... ... @@ -59,7 +59,7 @@ Example 1 : Dilation by a square on a gray-level image // Define a square SE of size 21x21 auto input = ...; auto rect = mln::make_rectangle2d(21,21); mln::se::rect2d rect(21,21); auto output = mln::morpho::structural::dilate(input, rect); ... ...
 #include #include #include #include #include #include ... ... @@ -128,7 +128,7 @@ int main(int argc, char** argv) auto nbh = mln::make_rectangle2d(size, size); mln::se::rect2d nbh(size, size); switch (vm["operator"].as()) { ... ...
 #ifndef MLN_CORE_SE_RECT2D_HPP #define MLN_CORE_SE_RECT2D_HPP #include #include #include /// \file namespace mln { namespace se { struct rect2d; /**************************/ /*** Implementation **/ /**************************/ /// \brief Define a dynamic rectangular window anchored at (0,0). /// Its width and height are always odd numbers to ensure symmetry. struct rect2d #ifndef MLN_DOXYGEN : dyn_neighborhood_base #endif { typedef std::true_type is_incremental; typedef std::true_type is_decomposable; typedef dyn_neighborhood dec_type; typedef dyn_neighborhood inc_type; /// Construct an empty rectangle rect2d() = default; /// Construct a rectangle of size (Width × Height). /// /// \param width The width of the rectangle. If \p width is even, it is /// rounded to the closest lower odd int. /// \param height The height of the rectangle. If \p height is even, it is /// rounded to the closest lower odd int. rect2d(int width, int height) { mln_precondition(width >= 0 && "A negative width was given."); mln_precondition(height >= 0 && "A negative height was given."); int xoffset = width / 2; int yoffset = height / 2; m_dpoints.pmin = {static_cast(-yoffset), static_cast(-xoffset)}; m_dpoints.pmax = {static_cast(yoffset+1), static_cast(xoffset+1)}; } /// \brief A WNeighborhood to be added when used incrementally inc_type inc() const { box2d b = this->m_dpoints; b.pmin = b.pmax - 1; return b; } /// \brief A WNeighborhood to be substracted when used incrementally dec_type dec() const { box2d b = this->m_dpoints; b.pmin -= 1; b.pmax = b.pmin + 1; return b; } /// \brief Return a range of SE offsets const mln::box2d& offsets() const { return m_dpoints; } /// \brief Return true for any non-empty rectangle bool decomposable() const { return !m_dpoints.empty(); } /// \brief Return an horizontal line of length \p Width and a vertical /// line of length \p Height corresponding to the SE decomposition. std::array decompose() const { const int v = m_dpoints.pmax - 1; const int h = m_dpoints.pmax - 1; periodic_line2d hline(point2d{0,1}, h); periodic_line2d vline(point2d{1,0}, v); return {{hline, vline}}; } private: box2d m_dpoints; }; } // end of namespace mln::se } // end of namespace mln #endif //! MLN_CORE_SE_RECT2D_HPP
 ... ... @@ -13,17 +13,6 @@ namespace mln { /// /// \brief Define a dynamic rectangular window /// struct rect2d; /// \defgroup Free functions /// \{ rect2d make_rectangle2d(unsigned height, unsigned width); rect2d make_rectangle2d(unsigned height, unsigned width, point2d center); /// \} namespace { ... ... @@ -73,67 +62,6 @@ namespace mln static const winc2_h_t winc2_h{}; } /**************************/ /*** Implementation **/ /**************************/ struct rect2d : dyn_neighborhood_base { typedef std::true_type is_incremental; typedef std::false_type is_separable; typedef dyn_neighborhood dec_type; typedef dyn_neighborhood inc_type; rect2d() = default; rect2d(const box2d& r) : dpoints(r) {} inc_type inc() const { box2d b = this->dpoints; b.pmin = b.pmax - 1; return b; } dec_type dec() const { box2d b = this->dpoints; b.pmin -= 1; b.pmax = b.pmin + 1; return b; } const box2d& offsets() const { return dpoints; } const box2d dpoints; }; inline rect2d make_rectangle2d(unsigned height, unsigned width) { mln_precondition(height % 2 == 1); mln_precondition(width % 2 == 1); int h = height / 2; int w = width / 2; box2d b = {point2d(-h, -w), point2d(h + 1, w + 1)}; return b; } inline rect2d make_rectangle2d(unsigned height, unsigned width, point2d center) { mln_precondition(height % 2 == 1); mln_precondition(width % 2 == 1); unsigned h = height / 2; unsigned w = width / 2; point2d uleft = center; point2d lright = center; uleft -= h; uleft -= w; lright += h + 1; lright += w + 1; box2d b = {uleft, lright}; return b; } } #endif // ! MLN_CORE_WIN2D_HPP
 ... ... @@ -2,7 +2,7 @@ #define MLN_MORPHO_CANVAS_DILATION_LIKE_SPE_HPP #include #include #include #include namespace mln ... ... @@ -23,9 +23,9 @@ namespace mln // might be costly due to cycle detection. template typename std::enable_if::value>::type dilation_like(const Image& ima_, const rect2d& nbh, Compare cmp, Image& output, OpTraits __op__) dilation_like(const Image& ima_, const se::rect2d& nbh, Compare cmp, Image& output, OpTraits __op__) { box2d r = nbh.dpoints; box2d r = nbh.offsets(); const I& ima = exact(ima_); if (r.shape() == 1) ... ... @@ -34,7 +34,7 @@ namespace mln } else if (r.shape() == 1) { rect2d h0{box2d{{0, r.pmin}, {1, r.pmax}}}; se::rect2d h0(r.pmax - r.pmin, 1); mln_concrete(I) tmp = transpose(ima); mln_concrete(I) out = imconcretize(tmp); morpho::canvas::dilation_like(tmp, h0, cmp, out, __op__); ... ... @@ -43,8 +43,8 @@ namespace mln else { rect2d h0{box2d{{0, r.pmin}, {1, r.pmax}}}; rect2d h1{box2d{{0, r.pmin}, {1, r.pmax}}}; se::rect2d h0(r.pmax - r.pmin, 1); se::rect2d h1(r.pmax - r.pmin, 1); image2d f; { ... ...