Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
greedy-plane-segmentation-ex2.cpp
Go to the documentation of this file.
1
16
29
30
57
58
60#include <iostream>
61#include <vector>
62#include <set>
63#include <map>
64#include <queue>
65#include "DGtal/base/Common.h"
66#include "DGtal/io/readers/VolReader.h"
67#include "DGtal/io/viewers/PolyscopeViewer.h"
68#include "DGtal/images/ImageSelector.h"
69#include "DGtal/images/imagesSetsUtils/SetFromImage.h"
70#include "DGtal/topology/DigitalSurface.h"
71#include "DGtal/topology/DigitalSetBoundary.h"
72#include "DGtal/graph/BreadthFirstVisitor.h"
73#include "DGtal/geometry/surfaces/COBANaivePlaneComputer.h"
74#include "DGtal/helpers/StdDefs.h"
75#include "ConfigExamples.h"
76
78
79using namespace std;
80using namespace DGtal;
81
83using namespace Z3i;
86// We choose the DigitalSetBoundary surface container in order to
87// segment connected or unconnected surfaces.
93typedef SurfelSet::iterator SurfelSetIterator;
105 std::size_t size;
106 inline VertexSize( const Vertex & aV, std::size_t aSize )
107 : v( aV ), size( aSize )
108 {}
109};
110
111inline
112bool operator<( const VertexSize & vs1, const VertexSize & vs2 )
113{
114 return vs1.size < vs2.size;
115}
116
117
119
120int main( int argc, char** argv )
121{
123 trace.info() << "Segments the surface at given threshold within given volume into digital planes of rational width num/den." << std::endl;
124 // Setting default options: ----------------------------------------------
125 // input file used:
126 string inputFilename = examplesPath + "samples/Al.100.vol" ;
127 trace.info() << "input file used " << inputFilename << std::endl;
128 // parameter threshold
129 unsigned int threshold = 0;
130 trace.info() << "the value that defines the isosurface in the image (an integer between 0 and 255)= " << threshold<< std::endl;
131 // parameter widthNum
132 unsigned int widthNum = 1;
133 trace.info() << "the numerator of the rational width (a non-null integer) =" << widthNum<< std::endl;
134 // parameter widthDen
135 unsigned int widthDen = 1;
136 trace.info() << "the denominator of the rational width (a non-null integer)= " << widthDen<< std::endl;
138
141 Image image = VolReader<Image>::importVol(inputFilename);
142 DigitalSet set3d (image.domain());
143 SetFromImage<DigitalSet>::append<Image>(set3d, image, threshold,255);
145
147 trace.beginBlock( "Set up digital surface." );
148 // We initializes the cellular grid space used for defining the
149 // digital surface.
150 KSpace ks;
151 bool ok = ks.init( set3d.domain().lowerBound(),
152 set3d.domain().upperBound(), true );
153 if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
154 SurfelAdjacency<KSpace::dimension> surfAdj( true ); // interior in all directions.
155 MyDigitalSurfaceContainer* ptrSurfContainer =
156 new MyDigitalSurfaceContainer( ks, set3d, surfAdj );
157 MyDigitalSurface digSurf( ptrSurfContainer ); // acquired
158 trace.endBlock();
160
162 Point p;
163 Dimension axis;
164 unsigned int j = 0;
165 unsigned int nb = digSurf.size();
166
167 // First pass to find biggest planes.
168 trace.beginBlock( "1) Segmentation first pass. Computes all planes so as to sort vertices by the plane size." );
169 std::map<Vertex,unsigned int> v2size;
170 NaivePlaneComputer planeComputer;
171 std::priority_queue<VertexSize> Q;
172 for ( ConstIterator it = digSurf.begin(), itE= digSurf.end(); it != itE; ++it )
173 {
174 if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
175 Vertex v = *it;
176 axis = ks.sOrthDir( v );
177 planeComputer.init( axis, 500, widthNum, widthDen );
178 // The visitor takes care of all the breadth-first traversal.
179 Visitor visitor( digSurf, v );
180 while ( ! visitor.finished() )
181 {
182 Visitor::Node node = visitor.current();
183 v = node.first;
184 axis = ks.sOrthDir( v );
185 p = ks.sCoords( ks.sDirectIncident( v, axis ) );
186 bool isExtended = planeComputer.extend( p );
187 if ( isExtended )
188 // surfel is in plane.
189 visitor.expand();
190 else // surfel is not in plane and should not be used in the visit.
191 visitor.ignore();
192 }
193 Q.push( VertexSize( v, planeComputer.size() ) );
194 }
195 trace.endBlock();
196
197 trace.beginBlock( "2) Segmentation second pass. Visits vertices from the one with biggest plane to the one with smallest plane." );
198 std::set<Vertex> processedVertices;
199 std::vector<SegmentedPlane*> segmentedPlanes;
200 std::map<Vertex,SegmentedPlane*> v2plane;
201 j = 0;
202 while ( ! Q.empty() )
203 {
204 if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
205 Vertex v = Q.top().v;
206 Q.pop();
207 if ( processedVertices.find( v ) != processedVertices.end() ) // already in set
208 continue; // process to next vertex
209
210 SegmentedPlane* ptrSegment = new SegmentedPlane;
211 segmentedPlanes.push_back( ptrSegment ); // to delete them afterwards.
212 axis = ks.sOrthDir( v );
213 ptrSegment->plane.init( axis, 500, widthNum, widthDen );
214 // The visitor takes care of all the breadth-first traversal.
215 Visitor visitor( digSurf, v );
216 while ( ! visitor.finished() )
217 {
218 Visitor::Node node = visitor.current();
219 v = node.first;
220 if ( processedVertices.find( v ) == processedVertices.end() )
221 { // Vertex is not in processedVertices
222 axis = ks.sOrthDir( v );
223 p = ks.sCoords( ks.sDirectIncident( v, axis ) );
224 bool isExtended = ptrSegment->plane.extend( p );
225 if ( isExtended )
226 { // surfel is in plane.
227 processedVertices.insert( v );
228 v2plane[ v ] = ptrSegment;
229 visitor.expand();
230 }
231 else // surfel is not in plane and should not be used in the visit.
232 visitor.ignore();
233 }
234 else // surfel is already in some plane.
235 visitor.ignore();
236 }
237 // Assign random color for each plane.
238 ptrSegment->color = Color( rand() % 256, rand() % 256, rand() % 256, 255 );
239 }
240 trace.endBlock();
242
244 PolyscopeViewer<> viewer( ks );
245 for ( std::map<Vertex,SegmentedPlane*>::const_iterator
246 it = v2plane.begin(), itE = v2plane.end();
247 it != itE; ++it )
248 {
249 viewer << it->second->color;
250 viewer << ks.unsigns( it->first );
251 }
253
255 for ( std::vector<SegmentedPlane*>::iterator
256 it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
257 it != itE; ++it )
258 delete *it;
259 segmentedPlanes.clear();
260 v2plane.clear();
262
263 viewer.show();
264 return 0;
265}
266
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
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:77
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
DigitalSurfaceContainer::SurfelConstIterator ConstIterator
ConstIterator begin() const
ConstIterator end() const
Aim: implements association bewteen points lying in a digital domain and values.
Definition Image.h:70
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])
void show() override
Starts the event loop and display of elements.
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
SurfelSet::iterator SurfelSetIterator
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
MyDigitalSurface::SurfelSet SurfelSet
BreadthFirstVisitor< MyDigitalSurface > Visitor
DigitalSetBoundary< KSpace, DigitalSet > MyDigitalSurfaceContainer
DGtal::int64_t InternalInteger
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
Z3i this namespace gathers the standard of types for 3D imagery.
KhalimskySpaceND< 3, Integer > KSpace
Definition StdDefs.h:146
DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet
Definition StdDefs.h:173
DGtal is the top-level namespace which contains all DGtal functions and types.
std::int64_t int64_t
signed 94-bit integer.
Definition BasicTypes.h:73
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:119
Trace trace
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())
VertexSize(const Vertex &aV, std::size_t aSize)
int main()
Definition testBits.cpp:56
Image image(domain)
TriMesh::Vertex Vertex