DGtal 1.4.0
Loading...
Searching...
No Matches
greedy-plane-segmentation-ex3.cpp
Go to the documentation of this file.
1
31#include <iostream>
32#include <vector>
33#include <set>
34#include <map>
35#include <queue>
36
37#include "DGtal/base/Common.h"
38#include "DGtal/io/readers/VolReader.h"
39
40#include "DGtal/io/Display3D.h"
41#include "DGtal/io/viewers/Viewer3D.h"
42#include "DGtal/io/DrawWithDisplay3DModifier.h"
43#include "DGtal/images/ImageSelector.h"
44#include "DGtal/images/imagesSetsUtils/SetFromImage.h"
45#include "DGtal/topology/DigitalSurface.h"
46#include "DGtal/topology/DigitalSetBoundary.h"
47#include "DGtal/graph/BreadthFirstVisitor.h"
48#include "DGtal/geometry/surfaces/COBANaivePlaneComputer.h"
49#include "DGtal/helpers/StdDefs.h"
50#include "ConfigExamples.h"
51
53
54using namespace std;
55using namespace DGtal;
56
58using namespace Z3i;
61// We choose the DigitalSetBoundary surface container in order to
62// segment connected or unconnected surfaces.
68typedef SurfelSet::iterator SurfelSetIterator;
74struct SegmentedPlane {
76 Color color;
77};
78struct VertexSize {
79 Vertex v;
80 unsigned int size;
81 inline VertexSize( const Vertex & aV, unsigned int aSize )
82 : v( aV ), size( aSize )
83 {}
84};
85
86inline
87bool operator<( const VertexSize & vs1, const VertexSize & vs2 )
88{
89 return vs1.size < vs2.size;
90}
92
94
95int main( int argc, char** argv )
96{
98 trace.info() << "Segments the surface at given threshold within given volume into digital planes of rational width num/den." << std::endl;
99 // Setting default options: ----------------------------------------------
100 // input file used:
101 string inputFilename = examplesPath + "samples/Al.100.vol" ;
102 trace.info() << "input file used " << inputFilename << std::endl;
103 // parameter threshold
104 unsigned int threshold = 0;
105 trace.info() << "the value that defines the isosurface in the image (an integer between 0 and 255)= " << threshold<< std::endl;
106 // parameter widthNum
107 unsigned int widthNum = 1;
108 trace.info() << "the numerator of the rational width (a non-null integer) =" << widthNum<< std::endl;
109 // parameter widthDen
110 unsigned int widthDen = 1;
111 trace.info() << "the denominator of the rational width (a non-null integer)= " << widthDen<< std::endl;
113
115 QApplication application(argc,argv);
117 Image image = VolReader<Image>::importVol(inputFilename);
118 DigitalSet set3d (image.domain());
119 SetFromImage<DigitalSet>::append<Image>(set3d, image, threshold,255);
121
123 trace.beginBlock( "Set up digital surface." );
124 // We initializes the cellular grid space used for defining the
125 // digital surface.
126 KSpace ks;
127 bool ok = ks.init( set3d.domain().lowerBound(),
128 set3d.domain().upperBound(), true );
129 if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
130 SurfelAdjacency<KSpace::dimension> surfAdj( true ); // interior in all directions.
131 MyDigitalSurfaceContainer* ptrSurfContainer =
132 new MyDigitalSurfaceContainer( ks, set3d, surfAdj );
133 MyDigitalSurface digSurf( ptrSurfContainer ); // acquired
134 trace.endBlock();
136
138 Point p;
139 Dimension axis;
140 unsigned int j = 0;
141 unsigned int nb = digSurf.size();
142
143 // First pass to find biggest planes.
144 trace.beginBlock( "1) Segmentation first pass. Computes all planes so as to sort vertices by the plane size." );
145 std::map<Vertex,unsigned int> v2size;
146 NaivePlaneComputer planeComputer;
147 std::priority_queue<VertexSize> Q;
148 std::vector<Point> layer;
149 for ( ConstIterator it = digSurf.begin(), itE= digSurf.end(); it != itE; ++it )
150 {
151 if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
152 Vertex v = *it;
153 axis = ks.sOrthDir( v );
154 planeComputer.init( axis, 500, widthNum, widthDen );
155 // The visitor takes care of all the breadth-first traversal.
156 Visitor visitor( digSurf, v );
157 layer.clear();
158 Visitor::Size currentSize = visitor.current().second;
159 while ( ! visitor.finished() )
160 {
161 Visitor::Node node = visitor.current();
162 v = node.first;
163 axis = ks.sOrthDir( v );
164 p = ks.sCoords( ks.sDirectIncident( v, axis ) );
165 if ( node.second != currentSize )
166 {
167 // std::cerr << "Layer " << currentSize << ", size=" << layer.size() << std::endl;
168 bool isExtended = planeComputer.extend( layer.begin(), layer.end() );
169 if ( ! isExtended )
170 break;
171 layer.clear();
172 currentSize = node.second;
173 }
174 layer.push_back( p );
175 visitor.expand();
176 }
177 // std::cerr << v << " -> " << planeComputer.size() << std::endl;
178 Q.push( VertexSize( v, planeComputer.size() ) );
179 }
180 trace.endBlock();
181
182 trace.beginBlock( "2) Segmentation second pass. Visits vertices from the one with biggest plane to the one with smallest plane." );
183 std::set<Vertex> processedVertices;
184 std::map<Vertex,SegmentedPlane*> v2plane;
185 std::vector<SegmentedPlane*> segmentedPlanes;
186 j = 0;
187 while ( ! Q.empty() )
188 {
189 if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
190 Vertex v = Q.top().v;
191 Q.pop();
192 if ( processedVertices.find( v ) != processedVertices.end() ) // already in set
193 continue; // process to next vertex
194
195 SegmentedPlane* ptrSegment = new SegmentedPlane;
196 segmentedPlanes.push_back( ptrSegment ); // to delete them afterwards.
197 axis = ks.sOrthDir( v );
198 ptrSegment->plane.init( axis, 500, widthNum, widthDen );
199 // The visitor takes care of all the breadth-first traversal.
200 Visitor visitor( digSurf, v );
201 while ( ! visitor.finished() )
202 {
203 Visitor::Node node = visitor.current();
204 v = node.first;
205 if ( processedVertices.find( v ) == processedVertices.end() )
206 { // Vertex is not in processedVertices
207 axis = ks.sOrthDir( v );
208 p = ks.sCoords( ks.sDirectIncident( v, axis ) );
209 bool isExtended = ptrSegment->plane.extend( p );
210 if ( isExtended )
211 { // surfel is in plane.
212 processedVertices.insert( v );
213 v2plane[ v ] = ptrSegment;
214 visitor.expand();
215 }
216 else // surfel is not in plane and should not be used in the visit.
217 visitor.ignore();
218 }
219 else // surfel is already in some plane.
220 visitor.ignore();
221 }
222 // Assign random color for each plane.
223 ptrSegment->color = Color( rand() % 256, rand() % 256, rand() % 256, 255 );
224 }
225 trace.endBlock();
227
229 Viewer3D<> viewer( ks );
230 viewer.show();
231 Color col( 255, 255, 120 );
232 for ( std::map<Vertex,SegmentedPlane*>::const_iterator
233 it = v2plane.begin(), itE = v2plane.end();
234 it != itE; ++it )
235 {
236 viewer << CustomColors3D( it->second->color, it->second->color );
237 viewer << ks.unsigns( it->first );
238 }
239 viewer << Viewer3D<>::updateDisplay;
241
243 for ( std::vector<SegmentedPlane*>::iterator
244 it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
245 it != itE; ++it )
246 delete *it;
247 segmentedPlanes.clear();
248 v2plane.clear();
250
251 return application.exec();
252}
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
std::pair< Vertex, Data > Node
FIXME.
Aim: A class that contains the COBA algorithm (Emilie Charrier, Lilian Buzer, DGCI2008) for recognizi...
void init(Dimension axis, InternalInteger diameter, InternalInteger widthNumerator=NumberTraits< InternalInteger >::ONE, InternalInteger widthDenominator=NumberTraits< InternalInteger >::ONE)
bool extend(const Point &p)
Structure representing an RGB triple with alpha component.
Definition Color.h:68
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
DigitalSurfaceContainer::SurfelConstIterator ConstIterator
Surfel Vertex
Defines the type for a vertex.
ConstIterator begin() const
ConstIterator end() const
KSpace::SurfelSet SurfelSet
Aim: implements association bewteen points lying in a digital domain and values.
Definition Image.h:70
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
Dimension sOrthDir(const SCell &s) const
Given a signed surfel [s], returns its orthogonal direction (ie, the coordinate where the surfel is c...
Cell unsigns(const SCell &p) const
Creates an unsigned cell from a signed one.
Point sCoords(const SCell &c) const
Return its digital coordinates.
SCell sDirectIncident(const SCell &p, Dimension k) const
Return the direct incident cell of [p] along [k] (the incident cell along [k])
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
void beginBlock(const std::string &keyword="")
std::ostream & info()
void progressBar(const double currentValue, const double maximalValue)
double endBlock()
virtual void show()
Overload QWidget method in order to add a call to updateList() method (to ensure that the lists are w...
MyDigitalSurface::ConstIterator ConstIterator
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
SurfelSet::iterator SurfelSetIterator
MyDigitalSurface::Vertex Vertex
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
MyDigitalSurface::ConstIterator ConstIterator
MyDigitalSurface::SurfelSet SurfelSet
BreadthFirstVisitor< MyDigitalSurface > Visitor
DigitalSetBoundary< KSpace, DigitalSet > MyDigitalSurfaceContainer
DGtal::int64_t InternalInteger
DGtal is the top-level namespace which contains all DGtal functions and types.
boost::int64_t int64_t
signed 94-bit integer.
Definition BasicTypes.h:74
bool operator<(PointVector< ptDim, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< ptDim, RightEuclideanRing, RightContainer > const &rhs)
Comparison operator on Points/Vectors (LesserThan).
DGtal::uint32_t Dimension
Definition Common.h:136
Trace trace
Definition Common.h:153
STL namespace.
ImageContainerBySTLVector< Domain, Value > Type
static void append(Set &aSet, const ForegroundPredicate &isForeground, typename Image::Domain::ConstIterator itBegin, typename Image::Domain::ConstIterator itEnd)
static ImageContainer importVol(const std::string &filename, const Functor &aFunctor=Functor())
int main()
Definition testBits.cpp:56
ImageContainerBySTLVector< Domain, Value > Image
TriMesh::Vertex Vertex