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 }
00110
00111 }
00112
00113
00114
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
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
00144
00145 typedef std::vector<Edge>::iterator EdgeIter;
00146 std::vector<Edge> edges = this->getEdges(smoothedImage);
00147 std::sort(edges.begin(), edges.end());
00148
00149
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
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
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 }
00218
00219 }
00220
00221 #endif