42 #ifndef _D_GEOCUTS_MINSURFACE_HPP_
43 #define _D_GEOCUTS_MINSURFACE_HPP_
46 #include <morphee/selement/include/selementNeighborList.hpp>
47 #include <morphee/selement/include/private/selementNeighborhood_T.hpp>
48 #include <morphee/image/include/private/image_T.hpp>
49 #include <morphee/image/include/imageUtils.hpp>
57 #ifndef __BOOST_INCLUDED__
58 #define __BOOST_INCLUDED__
60 #include <boost/config.hpp>
62 #include <boost/utility.hpp>
64 #include <boost/graph/graph_traits.hpp>
65 #include <boost/graph/adjacency_list.hpp>
71 #include <boost/version.hpp>
75 #include "../boost_ext/kolmogorov_max_flow_min_cost.hpp"
79 #include <boost/graph/connected_components.hpp>
92 typedef std::list<morceau> affine_par_morceaux;
94 using namespace geocuts;
103 template <
class T1,
class T2>
108 std::cout <<
"Enter function GeoCuts" << std::endl;
110 ASSERT_ALLOCATED(&imIn, &imGradx, &imGrady, &imMarker, &imOut);
111 ASSERT_SAME_SIZE(&imIn, &imGradx, &imGrady, &imMarker, &imOut);
120 typedef boost::adjacency_list_traits<boost::vecS, boost::vecS,
124 typedef boost::adjacency_list<
125 boost::listS, boost::vecS, boost::directedS,
126 boost::property<boost::vertex_name_t, std::string>,
128 boost::edge_capacity_t, double,
129 boost::property<boost::edge_residual_capacity_t, double,
130 boost::property<boost::edge_reverse_t,
131 Traits_d::edge_descriptor>>>>
136 boost::property_map<Graph_d, boost::edge_capacity_t>::type capacity =
137 boost::get(boost::edge_capacity, g);
139 boost::property_map<Graph_d, boost::edge_reverse_t>::type rev =
140 get(boost::edge_reverse, g);
142 boost::property_map<Graph_d, boost::edge_residual_capacity_t>::type
143 residual_capacity = get(boost::edge_residual_capacity, g);
145 Graph_d::edge_descriptor e1, e2, e3, e4;
146 Graph_d::vertex_descriptor vSource, vSink;
147 T1 numVertex =
maxVal(imIn);
150 std::cout <<
"build graph vertices" << std::endl;
151 std::cout <<
"number of vertices : " << numVertex << std::endl;
154 for (off_t i = 0; i < (off_t) pixelCount; i++) {
155 boost::add_vertex(g);
159 vSource = boost::add_vertex(g);
160 vSink = boost::add_vertex(g);
166 off_t strideY = width;
167 off_t strideZ = width * height;
168 for (
int z = 0; z < depth; z++) {
169 off_t p0Z = z * strideZ;
170 for (
int y = 0; y < height; y++) {
171 off_t p0Y = y * strideY;
172 for (
int x = 0; x < width; x++) {
173 off_t o1 = p0Z + p0Y + x;
176 vector<IntPoint> pts = filterStrElt(nl);
177 vector<IntPoint>::iterator itBegin, itEnd, it;
178 itBegin = pts.begin();
182 T2 marker = bufMarker[o1];
184 bool hasEdge =
false;
186 boost::tie(e4, hasEdge) = boost::add_edge(vSource, o1, g);
187 boost::tie(e3, hasEdge) = boost::add_edge(o1, vSource, g);
188 capacity[e4] = (std::numeric_limits<double>::max)();
189 capacity[e3] = (std::numeric_limits<double>::max)();
192 }
else if (marker == 3) {
193 boost::tie(e4, hasEdge) = boost::add_edge(o1, vSink, g);
194 boost::tie(e3, hasEdge) = boost::add_edge(vSink, o1, g);
195 capacity[e4] = (std::numeric_limits<double>::max)();
196 capacity[e3] = (std::numeric_limits<double>::max)();
201 for (it = itBegin; it != itEnd; it++) {
202 if (x + it->x > width - 1 || x + it->x < 0)
204 if (y + it->y > height - 1 || y + it->y < 0)
206 if (z + it->z > depth - 1 || z + it->z < 0)
209 off_t o2 = o1 + it->z * strideZ + it->y * strideY + it->x;
214 double cost = 1000 / (1 + 1.5 * (val1 - val2) * (val1 - val2));
216 bool hasEdge =
false;
217 boost::tie(e4, hasEdge) = boost::add_edge(o1, o2, g);
218 boost::tie(e3, hasEdge) = boost::add_edge(o2, o1, g);
229 for (it = itBegin; it != itEnd; it++) {
230 if (x + it->x > width - 1 || x + it->x < 0)
232 if (y + it->y > height - 1 || y + it->y < 0)
234 if (z + it->z > depth - 1 || z + it->z < 0)
237 off_t o2 = o1 + it->z * strideZ + it->y * strideY + it->x;
243 if (o2 > o1 + strideY) {
244 valDown = (T1) bufGrady[o2];
247 if (o2 < o1 + strideY) {
248 valUp = (T1) bufGrady[o2];
252 valRight = (T1) bufGradx[o2];
254 valLeft = (T1) bufGradx[o2];
257 double divergence = 10. * ((valLeft - valRight) + (valUp - valDown));
259 if (divergence < 0 && marker == 0) {
260 boost::tie(e4, hasEdge) = boost::add_edge(vSource, o1, g);
261 boost::tie(e3, hasEdge) = boost::add_edge(o1, vSource, g);
262 capacity[e4] = std::abs(divergence);
263 capacity[e3] = std::abs(divergence);
266 }
else if (divergence > 0 && marker == 0) {
267 boost::tie(e4, hasEdge) = boost::add_edge(o1, vSink, g);
268 boost::tie(e3, hasEdge) = boost::add_edge(vSink, o1, g);
269 capacity[e4] = divergence;
270 capacity[e3] = divergence;
278 boost::property_map<Graph_d, boost::vertex_index_t>::type indexmap =
279 boost::get(boost::vertex_index, g);
280 std::vector<boost::default_color_type> color(boost::num_vertices(g));
282 std::cout <<
"Compute Max flow" << std::endl;
283 #if BOOST_VERSION >= 104700
285 boykov_kolmogorov_max_flow(g, capacity, residual_capacity, rev,
286 &color[0], indexmap, vSource, vSink);
288 double flow = kolmogorov_max_flow(g, capacity, residual_capacity, rev,
289 &color[0], indexmap, vSource, vSink);
292 std::cout <<
"c The total flow:" << std::endl;
293 std::cout <<
"s " << flow << std::endl << std::endl;
296 for (off_t o1 = 0; o1 < (off_t) pixelCount; o1++) {
297 if (color[o1] == color[vSource])
299 else if (color[o1] == 1)
301 else if (color[o1] == color[vSink])
313 template <
class T1,
class T2>
317 std::cout <<
"Enter function Geo-Cuts Watershed" << std::endl;
319 ASSERT_ALLOCATED(&imIn, &imMarker, &imOut);
320 ASSERT_SAME_SIZE(&imIn, &imMarker, &imOut);
327 typedef boost::adjacency_list_traits<boost::vecS, boost::vecS,
331 typedef boost::adjacency_list<
332 boost::vecS, boost::vecS, boost::directedS,
333 boost::property<boost::vertex_name_t, std::string>,
335 boost::edge_capacity_t, double,
336 boost::property<boost::edge_residual_capacity_t, double,
337 boost::property<boost::edge_reverse_t,
338 Traits_d::edge_descriptor>>>>
343 boost::property_map<Graph_d, boost::edge_capacity_t>::type capacity =
344 boost::get(boost::edge_capacity, g);
346 boost::property_map<Graph_d, boost::edge_reverse_t>::type rev =
347 get(boost::edge_reverse, g);
349 boost::property_map<Graph_d, boost::edge_residual_capacity_t>::type
350 residual_capacity = get(boost::edge_residual_capacity, g);
352 Graph_d::edge_descriptor e1, e2, e3, e4;
353 Graph_d::vertex_descriptor vSource, vSink;
354 T1 numVertex =
maxVal(imIn);
358 std::cout <<
"build graph vertices" << std::endl;
359 std::cout <<
"number of vertices : " << numVertex << std::endl;
361 std::cout <<
"build graph vertices" << std::endl;
363 for (off_t i = 0; i < (off_t) pixelCount; i++) {
364 boost::add_vertex(g);
368 vSource = boost::add_vertex(g);
369 vSink = boost::add_vertex(g);
377 off_t strideY = width;
378 off_t strideZ = width * height;
379 for (
int z = 0; z < depth; z++) {
380 off_t p0Z = z * strideZ;
381 for (
int y = 0; y < height; y++) {
382 off_t p0Y = y * strideY;
383 for (
int x = 0; x < width; x++) {
384 off_t o1 = p0Z + p0Y + x;
387 vector<IntPoint> pts = filterStrElt(nl);
388 vector<IntPoint>::iterator itBegin, itEnd, it;
389 itBegin = pts.begin();
393 T2 marker = bufMarker[o1];
395 bool hasEdge =
false;
397 boost::tie(e4, hasEdge) = boost::add_edge(vSource, o1, g);
398 boost::tie(e3, hasEdge) = boost::add_edge(o1, vSource, g);
399 capacity[e4] = (std::numeric_limits<double>::max)();
400 capacity[e3] = (std::numeric_limits<double>::max)();
403 }
else if (marker == 3) {
404 boost::tie(e4, hasEdge) = boost::add_edge(o1, vSink, g);
405 boost::tie(e3, hasEdge) = boost::add_edge(vSink, o1, g);
406 capacity[e4] = (std::numeric_limits<double>::max)();
407 capacity[e3] = (std::numeric_limits<double>::max)();
412 for (it = itBegin; it != itEnd; it++) {
413 if (x + it->x > width - 1 || x + it->x < 0)
415 if (y + it->y > height - 1 || y + it->y < 0)
417 if (z + it->z > depth - 1 || z + it->z < 0)
420 off_t o2 = o1 + it->z * strideZ + it->y * strideY + it->x;
425 double valeur = std::abs((
double) (val2 - val1));
426 double cost = 256 / (1 +
std::pow(valeur, 2));
429 bool hasEdge =
false;
430 boost::tie(e4, hasEdge) = boost::add_edge(o1, o2, g);
431 boost::tie(e3, hasEdge) = boost::add_edge(o2, o1, g);
440 std::cout <<
"number of Edges : " << numEdges << std::endl;
442 std::cout <<
"Compute Max flow" << std::endl;
443 boost::property_map<Graph_d, boost::vertex_index_t>::type indexmap =
444 boost::get(boost::vertex_index, g);
445 std::vector<boost::default_color_type> color(boost::num_vertices(g));
446 #if BOOST_VERSION >= 104700
448 boykov_kolmogorov_max_flow(g, capacity, residual_capacity, rev,
449 &color[0], indexmap, vSource, vSink);
451 double flow = kolmogorov_max_flow(g, capacity, residual_capacity, rev,
452 &color[0], indexmap, vSource, vSink);
454 std::cout <<
"c The total flow:" << std::endl;
455 std::cout <<
"s " << flow << std::endl << std::endl;
458 for (off_t o1 = 0; o1 < (off_t) pixelCount; o1++) {
459 if (color[o1] == color[vSource])
461 else if (color[o1] == color[vSink])
463 else if (color[o1] == 1)
475 template <
class T1,
class T2>
480 ASSERT_ALLOCATED(&imIn, &imMarker, &imOut);
481 ASSERT_SAME_SIZE(&imIn, &imMarker, &imOut);
488 typedef boost::adjacency_list_traits<boost::vecS, boost::vecS,
492 typedef boost::adjacency_list<
493 boost::listS, boost::vecS, boost::directedS,
494 boost::property<boost::vertex_name_t, std::string>,
496 boost::edge_capacity_t, double,
497 boost::property<boost::edge_residual_capacity_t, double,
498 boost::property<boost::edge_reverse_t,
499 Traits_d::edge_descriptor>>>>
504 boost::property_map<Graph_d, boost::edge_capacity_t>::type capacity =
505 boost::get(boost::edge_capacity, g);
507 boost::property_map<Graph_d, boost::edge_reverse_t>::type rev =
508 get(boost::edge_reverse, g);
510 boost::property_map<Graph_d, boost::edge_residual_capacity_t>::type
511 residual_capacity = get(boost::edge_residual_capacity, g);
513 Graph_d::edge_descriptor e1, e2, e3, e4;
514 Graph_d::vertex_descriptor vSource, vSink;
516 std::cout <<
"build graph vertices" << std::endl;
519 size_t numVertex = pixelCount;
520 size_t numLabels =
maxVal(imMarker);
522 for (off_t i = 0; i < (off_t) pixelCount; i++) {
523 boost::add_vertex(g);
527 std::cout <<
"number of Labels: " << numLabels << std::endl;
528 std::cout <<
"number of vertices: " << numVertex << std::endl;
530 vSource = boost::add_vertex(g);
531 vSink = boost::add_vertex(g);
533 std::cout <<
"build graph edges" << std::endl;
539 off_t strideY = width;
540 off_t strideZ = width * height;
541 for (
int z = 0; z < depth; z++) {
542 off_t p0Z = z * strideZ;
543 for (
int y = 0; y < height; y++) {
544 off_t p0Y = y * strideY;
545 for (
int x = 0; x < width; x++) {
546 off_t o1 = p0Z + p0Y + x;
549 vector<IntPoint> pts = filterStrElt(nl);
550 vector<IntPoint>::iterator itBegin, itEnd, it;
551 itBegin = pts.begin();
556 for (it = itBegin; it != itEnd; it++) {
557 if (x + it->x > width - 1 || x + it->x < 0)
559 if (y + it->y > height - 1 || y + it->y < 0)
561 if (z + it->z > depth - 1 || z + it->z < 0)
564 off_t o2 = o1 + it->z * strideZ + it->y * strideY + it->x;
570 double cost = 10000.0 / (1.0 + 1.5 * (val1 - val2) * (val1 - val2));
572 bool hasEdge =
false;
573 boost::tie(e4, hasEdge) = boost::add_edge(o1, o2, g);
574 boost::tie(e3, hasEdge) = boost::add_edge(o2, o1, g);
575 capacity[e4] = cost + 1;
576 capacity[e3] = cost + 1;
584 for (T2 nbk = 2; nbk <= numLabels; nbk++) {
586 for (off_t o0 = 0; o0 < (off_t) pixelCount; o0++) {
587 T2 val1 = bufMarker[o0];
590 double cost = std::numeric_limits<double>::max();
593 boost::tie(e4, hasEdge) = boost::edge(vSource, o0, g);
595 boost::tie(e4, hasEdge) = boost::add_edge(vSource, o0, g);
596 boost::tie(e3, hasEdge) = boost::add_edge(o0, vSource, g);
602 }
else if (val1 > 1 && val1 != nbk) {
603 boost::tie(e4, hasEdge) = boost::edge(val2, vSink, g);
605 boost::tie(e4, hasEdge) = boost::add_edge(o0, vSink, g);
606 boost::tie(e3, hasEdge) = boost::add_edge(vSink, o0, g);
615 std::cout <<
"Compute Max flow" << nbk << std::endl;
616 boost::property_map<Graph_d, boost::vertex_index_t>::type indexmap =
617 boost::get(boost::vertex_index, g);
618 std::vector<boost::default_color_type> color(boost::num_vertices(g));
620 #if BOOST_VERSION >= 104700
622 boykov_kolmogorov_max_flow(g, capacity, residual_capacity, rev,
623 &color[0], indexmap, vSource, vSink);
625 double flow = kolmogorov_max_flow(g, capacity, residual_capacity, rev,
626 &color[0], indexmap, vSource, vSink);
629 std::cout <<
"c The total flow:" << std::endl;
630 std::cout <<
"s " << flow << std::endl << std::endl;
633 for (off_t o1 = 0; o1 < (off_t) pixelCount; o1++) {
634 T1 val1 = (int) bufIn[o1];
635 T2 val2 = (int) bufOut[o1];
636 T2 val3 = (int) bufMarker[o1];
639 if (color[val1] == color[vSource])
640 bufOut[o1] = (T2) nbk;
645 boost::tie(e4, hasEdge) = boost::edge(vSource, o1, g);
647 boost::remove_edge(vSource, o1, g);
648 boost::remove_edge(o1, vSource, g);
650 }
else if (val3 > 1) {
651 boost::tie(e4, hasEdge) = boost::edge(o1, vSink, g);
653 boost::remove_edge(o1, vSink, g);
654 boost::remove_edge(vSink, o1, g);
size_t getDepth() const
Get image depth (Z)
Definition: DBaseImage.h:90
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:80
size_t getPixelCount() const
Get the number of pixels.
Definition: DBaseImage.h:160
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:85
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:105
Base structuring element.
Definition: DStructuringElement.h:68
RES_T pow(const Image< T1 > &imIn, Image< T2 > &imOut, double exponent=2)
pow() - power of an image
Definition: DImageArith.hpp:905
T maxVal(const Image< T > &imIn, bool onlyNonZero=false)
maxVal() - Max value of an image
Definition: DMeasures.hpp:348
RES_T geoCuts(const Image< T1 > &imIn, const Image< T1 > &imGradx, const Image< T1 > &imGrady, const Image< T2 > &imMarker, const StrElt &nl, Image< T2 > &imOut)
Returns Geo Cuts algorithm.
Definition: MinSurfaces.hpp:104
RES_T geoCutsMultiway_MinSurfaces(const Image< T1 > &imIn, const Image< T2 > &imMarker, const StrElt &nl, Image< T2 > &imOut)
Multiple object segmentation, Geo Cuts algorithm on a pixel adjacency graph, ImMarker is composed of ...
Definition: MinSurfaces.hpp:476
RES_T geoCutsMinSurfaces(const Image< T1 > &imIn, const Image< T2 > &imMarker, const StrElt &nl, Image< T2 > &imOut)
Geo Cuts algorithm on a pixel adjacency graph, ImMarker is composed of three values 0 for unmarked pi...
Definition: MinSurfaces.hpp:314
Definition: GeoCutsAlgo_impl_T.hpp:57