21 #ifndef mia_internal_seededwatershed_hh 22 #define mia_internal_seededwatershed_hh 32 class TSeededWS :
public watershed_traits<dim>::Handler::Product {
34 typedef typename watershed_traits<dim>::PNeighbourhood PNeighbourhood;
35 typedef typename PNeighbourhood::element_type::value_type MPosition;
36 typedef typename watershed_traits<dim>::Handler Handler;
37 typedef typename watershed_traits<dim>::FileHandler FileHandler;
38 typedef typename Handler::Product CFilter;
39 typedef typename FileHandler::Instance::DataKey DataKey;
40 typedef typename CFilter::Pointer PFilter;
41 typedef typename CFilter::Image CImage;
42 typedef typename CImage::Pointer PImage;
43 typedef typename CImage::dimsize_type Position;
46 TSeededWS(
const DataKey& mask_image, PNeighbourhood neighborhood,
47 bool with_borders,
bool input_is_gradient);
49 template <
template <
typename>
class Image,
typename T>
50 typename TSeededWS<dim>::result_type operator () (
const Image<T>& data)
const;
52 virtual PImage do_filter(
const CImage& image)
const;
54 DataKey m_label_image_key;
55 PNeighbourhood m_neighborhood;
61 class TSeededWSFilterPlugin:
public watershed_traits<dim>::Handler::Interface {
63 typedef typename watershed_traits<dim>::PNeighbourhood PNeighbourhood;
64 typedef typename watershed_traits<dim>::Handler Handler;
65 typedef typename watershed_traits<dim>::FileHandler FileHandler;
66 typedef typename Handler::Product CFilter;
68 TSeededWSFilterPlugin();
70 virtual CFilter *do_create()
const;
71 virtual const std::string do_get_descr()
const;
72 std::string m_seed_image_file;
73 PNeighbourhood m_neighborhood;
75 bool m_input_is_gradient;
78 template <
template <
typename>
class Image,
typename T,
typename S,
typename N,
typename R,
int dim,
bool supported>
80 static R apply(
const Image<T>& image,
const Image<S>& seed, N n,
bool with_borders);
83 template <
template <
typename>
class Image,
typename T,
typename S,
typename N,
typename R,
int dim>
84 struct seeded_ws<Image, T, S, N, R, dim, false> {
85 static R apply(
const Image<T>& ,
const Image<S>& , N ,
bool ) {
86 throw create_exception<std::invalid_argument>(
"C2DRunSeededWS: seed data type '", __type_descr<S>::value,
"' not supported");
92 template <
template <
typename>
class Image,
typename T,
typename N,
typename R,
int dim>
93 struct dispatch_RunSeededWS :
public TFilter<R> {
95 dispatch_RunSeededWS(N neighborhood,
const Image<T>& image,
bool with_borders):
96 m_neighborhood(neighborhood),
98 m_with_borders(with_borders)
101 template <
typename S>
102 R operator () (
const Image<S>& seed)
const {
103 const bool supported = std::is_integral<S>::value && !std::is_same<S, bool>::value;
104 return seeded_ws<Image, T, S, N, R, dim, supported>::apply(m_image, seed, m_neighborhood, m_with_borders);
107 const Image<T>& m_image;
112 template <
typename L,
typename Position>
113 struct PixelWithLocation {
119 template <
typename L,
typename Position>
120 bool operator < (const PixelWithLocation<L,Position>& lhs,
const PixelWithLocation<L,Position>& rhs)
122 mia::less_then<Position> l;
123 return lhs.value > rhs.value||
124 ( lhs.value == rhs.value && l(rhs.pos, lhs.pos));
127 template <
template <
typename>
class Image,
typename T,
typename S,
int dim>
128 class TRunSeededWatershed {
130 typedef typename watershed_traits<dim>::PNeighbourhood PNeighbourhood;
131 typedef typename PNeighbourhood::element_type::value_type MPosition;
132 typedef typename watershed_traits<dim>::Handler Handler;
133 typedef typename Handler::Product CFilter;
134 typedef typename CFilter::Pointer PFilter;
135 typedef typename CFilter::Image CImage;
136 typedef typename CImage::Pointer PImage;
137 typedef typename CImage::dimsize_type Position;
140 TRunSeededWatershed(
const Image<T>& image,
const Image<S>& seed, PNeighbourhood neighborhood,
bool with_borders);
143 void add_neighborhood(
const PixelWithLocation<S, Position>& pixel);
144 const Image<T>& m_image;
145 const Image<S>& m_seed;
146 PNeighbourhood m_neighborhood;
147 Image<unsigned char> m_visited;
148 Image<unsigned char> m_stored;
151 std::priority_queue<PixelWithLocation<S, Position> > m_seeds;
156 template <
template <
typename>
class Image,
typename T,
typename S,
int dim>
157 TRunSeededWatershed<Image, T, S, dim>::TRunSeededWatershed(
const Image<T>& image,
const Image<S>& seed,
158 PNeighbourhood neighborhood,
bool with_borders):
161 m_neighborhood(neighborhood),
162 m_visited(seed.get_size()),
163 m_stored(seed.get_size()),
164 m_watershed(
std::numeric_limits<S>::max()),
165 m_with_borders(with_borders)
167 m_result =
new Image<S>(seed.get_size(), image);
168 m_presult.reset(m_result);
171 template <
template <
typename>
class Image,
typename T,
typename S,
int dim>
172 void TRunSeededWatershed<Image, T, S, dim>::add_neighborhood(
const PixelWithLocation<S, Position>& pixel)
174 PixelWithLocation<S, Position> new_pixel;
175 new_pixel.label = pixel.label;
176 bool hit_boundary =
false;
177 for (
auto i = m_neighborhood->begin(); i != m_neighborhood->end(); ++i) {
178 Position new_pos( pixel.pos + *i);
179 if (new_pos != pixel.pos && new_pos < m_seed.get_size()) {
180 if (!m_visited(new_pos)) {
181 if (!m_stored(new_pos) ) {
182 new_pixel.value = m_image(new_pos);
183 new_pixel.pos = new_pos;
184 m_seeds.push(new_pixel);
185 m_stored(new_pos) = 1;
188 hit_boundary |= (*m_result)(new_pos) != pixel.label &&
189 (*m_result)(new_pos) != m_watershed;
194 if (!m_visited(pixel.pos)) {
195 m_visited(pixel.pos) =
true;
196 (*m_result)(pixel.pos) = (m_with_borders && hit_boundary) ? m_watershed : pixel.label;
200 template <
template <
typename>
class Image,
typename T,
typename S,
int dim>
201 typename TRunSeededWatershed<Image,T,S,dim>::PImage
202 TRunSeededWatershed<Image,T,S,dim>::run()
205 auto iv = m_visited.begin();
206 auto is = m_seed.begin_range(Position::_0, m_seed.get_size());
207 auto es = m_seed.end_range(Position::_0, m_seed.get_size());
208 auto ir = m_result->begin();
209 auto ii = m_image.begin();
210 auto ist = m_stored.begin();
212 PixelWithLocation<S, Position> pixel;
218 pixel.pos = is.pos();
223 ++iv; ++is; ++ir; ++ist; ++ii;
226 while (!m_seeds.empty()) {
227 auto p = m_seeds.top();
234 template <
template <
typename>
class Image,
typename T,
typename S,
typename N,
typename R,
int dim,
bool supported>
235 R seeded_ws<Image,T,S,N,R,dim,supported>::apply(
const Image<T>& image,
236 const Image<S>& seed, N neighborhood,
bool with_borders)
238 TRunSeededWatershed<Image, T, S, dim> ws(image, seed, neighborhood, with_borders);
243 TSeededWS<dim>::TSeededWS(
const DataKey& label_image_key, PNeighbourhood neighborhood,
bool with_borders,
bool input_is_gradient):
244 m_label_image_key(label_image_key),
245 m_neighborhood(neighborhood),
246 m_with_borders(with_borders)
249 if (!input_is_gradient)
250 m_togradnorm = Handler::instance().produce(
"gradnorm");
254 template <
template <
typename>
class Image,
typename T>
255 typename TSeededWS<dim>::result_type TSeededWS<dim>::operator () (
const Image<T>& data)
const 258 auto in_image_list = m_label_image_key.get();
259 if (!in_image_list || in_image_list->empty())
260 throw create_exception<std::runtime_error>(
"C2DSeededWS: no seed image could be loaded");
262 if (in_image_list->size() > 1)
263 cvwarn() <<
"C2DSeededWS:got more than one seed image. Ignoring all but first";
265 auto seed = (*in_image_list)[0];
266 if (seed->get_size() != data.get_size()) {
267 throw create_exception<std::invalid_argument>(
"C2DSeededWS: seed and input differ in size: seed " , seed->get_size()
268 ,
", input " , data.get_size());
270 dispatch_RunSeededWS<Image, T, PNeighbourhood, PImage, dim> ws(m_neighborhood, data, m_with_borders);
275 typename TSeededWS<dim>::PImage TSeededWS<dim>::do_filter(
const CImage& image)
const 279 auto grad = m_togradnorm->filter(image);
289 TSeededWSFilterPlugin<dim>::TSeededWSFilterPlugin():
290 Handler::Interface(
"sws"),
291 m_with_borders(false),
292 m_input_is_gradient(false)
295 "seed input image containing the lables for the initial regions"));
296 this->add_parameter(
"n",
make_param(m_neighborhood,
"sphere:r=1",
false,
"Neighborhood for watershead region growing"));
297 this->add_parameter(
"mark",
new CBoolParameter(m_with_borders,
false,
"Mark the segmented watersheds with a special gray scale value"));
298 this->add_parameter(
"grad",
new CBoolParameter(m_input_is_gradient,
false,
"Interpret the input image as gradient. "));
302 typename TSeededWSFilterPlugin<dim>::CFilter *TSeededWSFilterPlugin<dim>::do_create()
const 304 auto seed = FileHandler::instance().load_to_pool(m_seed_image_file);
305 return new TSeededWS<dim>(seed, m_neighborhood, m_with_borders, m_input_is_gradient);
309 const std::string TSeededWSFilterPlugin<dim>::do_get_descr()
const 311 return "seeded watershead. The algorithm extracts exactly so " 312 "many reagions as initial labels are given in the seed image.";
CParameter * make_param(T &value, bool required, const char *descr)
base class for all filer type functors.
CTParameter< bool > CBoolParameter
boolean parameter
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
static F::result_type filter(const F &f, const B &b)
vstream & cvwarn()
send warnings to this stream adapter
#define NS_MIA_END
conveniance define to end the mia namespace