Champfer distance transform =========================== .. code:: cpp template concept bool Image_with_Neighborhood_and_Extension = Image && Neighborhood && Extension; template < Image_with_Neighborhood_and_Extension Img, ConvexDomain, Applyable > Image chamfer_distance_transform(const Img& ima, const NeighborhoodMask& nbh_mask) { auto ima_res = copy(ima); extension::fill(ima, numeric_limits::max()); // forward pass for(auto [&pix_res, pix] : zip(ima_res.pixels(), ima.pixels())) { if(pix->val()) { pix_res.val() = accumulate( nbh_mask(pix_res.neighbors()), numeric_limits::max(), [&pix_res](auto vmin, auto&& neighbor) { if (neighbor->index() < pix_res->index()) { return min(vmin, neighbor->val() + neighbor->weight()) } } ); } else { pix_res->val() = 0; } } // backward pass for(auto [&pix_res, pix] : zip_backward(ima_res.pixels(), ima.pixels())) { pix_res.val() = accumulate( nbh_mask(pix_res.neighbors()), numeric_limits::max(), [&pix_res](auto vmin, auto&& neighbor) { if (neighbor->index() > pix_res->index()) { return min(vmin, neighbor->val() + neighbor->weight()) } } ); } return ima_res; }