segmenterFelzenszwalb.h

Go to the documentation of this file.
00001 
00015 #ifndef DLR_COMPUTERVISION_SEGMENTERFELZENSZWALB_H
00016 #define DLR_COMPUTERVISION_SEGMENTERFELZENSZWALB_H
00017 
00018 #include <vector>
00019 #include <dlrComputerVision/disjointSet.h>
00020 #include <dlrComputerVision/filter.h>
00021 #include <dlrComputerVision/image.h>
00022 #include <dlrComputerVision/kernels.h>
00023 #include <dlrComputerVision/utilities.h>
00024 
00025 namespace dlr {
00026 
00027   namespace computerVision {
00028 
00039     class SegmenterFelzenszwalb {
00040     public:
00041 
00042       struct Edge {
00043         size_t end0;
00044         size_t end1;
00045         float weight;
00046       };
00047 
00048       
00049       SegmenterFelzenszwalb(float k = 200.0f,
00050                             float sigma = 0.8f,
00051                             size_t minSegmentSize = 20);
00052 
00053       
00054       virtual
00055       ~SegmenterFelzenszwalb() {}
00056 
00057 
00058       virtual Array2D<UnsignedInt32>
00059       getLabelArray();
00060 
00061       
00062       virtual Array2D<UnsignedInt32>
00063       getLabelArray(UnsignedInt32& numberOfSegments,
00064                     std::vector<size_t>& segmentSizes);
00065 
00066 
00067       template <ImageFormat FORMAT>
00068       void
00069       segment(const Image<FORMAT>& inputImage);
00070 
00071     protected:
00072 
00073       typedef privateCode::DisjointSet<float> Segment;
00074 
00075 
00076       inline float
00077       getCost(const Segment& C_i, const Segment& C_j);
00078 
00079 
00080       std::vector<SegmenterFelzenszwalb::Edge>
00081       getEdges(const Image<GRAY_FLOAT32>& inImage);
00082 
00083       
00084       inline void
00085       setEdge(Edge& edge, size_t index0, size_t index1,
00086               Image<GRAY_FLOAT32> inImage);
00087 
00088       
00089       inline void
00090       updateCost(Segment& C_i, float weight);
00091 
00092 
00093       numeric::Index2D m_imageSize;
00094       float m_k;
00095       size_t m_minimumSegmentSize;
00096       numeric::Array1D<Segment> m_segmentation;
00097       float m_sigma;
00098       size_t m_smoothSize;
00099       
00100     };
00101 
00102 
00103     inline bool
00104     operator<(const SegmenterFelzenszwalb::Edge& arg0,
00105               const SegmenterFelzenszwalb::Edge& arg1) {
00106       return arg0.weight < arg1.weight;
00107     }
00108     
00109   } // namespace computerVision
00110   
00111 } // namespace dlr
00112 
00113 
00114 /* ============ Definitions of inline & template functions ============ */
00115 
00116 
00117 #include <cmath>
00118 
00119 namespace dlr {
00120 
00121   namespace computerVision {
00122 
00123     template <ImageFormat FORMAT>
00124     void
00125     SegmenterFelzenszwalb::
00126     segment(const Image<FORMAT>& inputImage)
00127     {
00128       m_imageSize.setValue(inputImage.rows(), inputImage.columns());
00129       
00130       // Smooth the image slightly to reduce artifacts.
00131       Image<GRAY_FLOAT32> smoothedImage;
00132       if(m_sigma == 0.0) {
00133         smoothedImage = convertColorspace<GRAY_FLOAT32>(inputImage);
00134       } else {
00135         Kernel<double> gaussian =
00136           getGaussianKernel<double>(m_smoothSize, m_smoothSize,
00137                                     m_sigma, m_sigma);
00138         smoothedImage = 
00139           filter2D<GRAY_FLOAT32, GRAY_FLOAT32>(
00140             gaussian, inputImage, Float32(0));
00141       }
00142 
00143       // Get a vector of the edges in the image, sorted in ascending
00144       // order.
00145       typedef std::vector<Edge>::iterator EdgeIter;
00146       std::vector<Edge> edges = this->getEdges(smoothedImage);
00147       std::sort(edges.begin(), edges.end());
00148 
00149       // Start with segmentation S^0, where every vertex is its own component.
00150       typedef numeric::Array1D<Segment>::iterator SegmentIter;
00151       m_segmentation.reinit(smoothedImage.size());
00152       for(SegmentIter segmentIter = m_segmentation.begin();
00153           segmentIter != m_segmentation.end(); ++segmentIter) {
00154         segmentIter->setPayload(m_k);        
00155       }
00156       
00157       // Iteratively merge segments, as described in the paper.
00158       EdgeIter edgeIter = edges.begin();
00159       while(edgeIter != edges.end()) {
00160         Segment& C_i = m_segmentation[edgeIter->end0].find();
00161         Segment& C_j = m_segmentation[edgeIter->end1].find();
00162         if(&C_i != &C_j) {
00163           float threshold = this->getCost(C_i, C_j);
00164           if(edgeIter->weight <= threshold) {
00165             C_i.merge(C_j);
00166             this->updateCost(C_i, edgeIter->weight);
00167           }
00168         }
00169         ++edgeIter;
00170       }
00171 
00172       // Merge any undersize segments, merging weak edges first.
00173       edgeIter = edges.begin();
00174       while(edgeIter != edges.end()) {
00175         Segment& C_i = m_segmentation[edgeIter->end0].find();
00176         Segment& C_j = m_segmentation[edgeIter->end1].find();
00177         if(C_i.getSize() < m_minimumSegmentSize
00178            || C_i.getSize() < m_minimumSegmentSize) {
00179           C_i.merge(C_j);
00180         }
00181         ++edgeIter;
00182       }
00183     
00184     }
00185 
00186     
00187     inline float
00188     SegmenterFelzenszwalb::
00189     getCost(const Segment& C_i, const Segment& C_j)
00190     {
00191       return std::min(C_i.getPayload(), C_j.getPayload());
00192     }
00193 
00194 
00195     inline void
00196     SegmenterFelzenszwalb::
00197     setEdge(Edge& edge, size_t index0, size_t index1,
00198             Image<GRAY_FLOAT32> inImage)
00199     {
00200       edge.end0 = index0;
00201       edge.end1 = index1;
00202       edge.weight = inImage[index1] - inImage[index0];
00203       if(edge.weight < 0.0) {
00204         edge.weight = -edge.weight;
00205       }
00206     }
00207 
00208   
00209     inline void
00210     SegmenterFelzenszwalb::
00211     updateCost(Segment& C_i, float weight)
00212     {
00213       Segment& head = C_i.find();
00214       head.setPayload(weight + m_k / head.getSize());
00215     }
00216   
00217   } // namespace computerVision
00218 
00219 } // namespace dlr
00220 
00221 #endif /* #ifndef DLR_COMPUTERVISION_SEGMENTERFELZENSZWALB_H */

Generated on Wed Jun 25 14:34:10 2008 for dlrComputerVision Utility Library by  doxygen 1.5.5