connectedComponents.h
Go to the documentation of this file.00001
00015 #ifndef _DLRCOMPUTERVISION_CONNECTEDCOMPONENTS_H_
00016 #define _DLRCOMPUTERVISION_CONNECTEDCOMPONENTS_H_
00017
00018 #include <list>
00019 #include <dlrComputerVision/imageFormat.h>
00020 #include <dlrComputerVision/image.h>
00021
00022 namespace dlr {
00023
00024 namespace computerVision {
00025
00044 template<ImageFormat FORMAT_OUT, ImageFormat FORMAT_IN>
00045 Image<FORMAT_OUT>
00046 connectedComponents(const Image<FORMAT_IN>& inputImage);
00047
00048
00072 template<ImageFormat FORMAT_OUT, ImageFormat FORMAT_IN>
00073 Image<FORMAT_OUT>
00074 connectedComponents(const Image<FORMAT_IN>& inputImage,
00075 size_t& numberOfComponents);
00076
00077 }
00078
00079 }
00080
00081
00082
00083
00084
00085 #include <cmath>
00086
00087 namespace dlr {
00088
00089 namespace computerVision {
00090
00092 namespace privateCode {
00093
00094
00095
00096
00097
00098
00099 bool
00100 propagateLabel(size_t label, size_t node, std::vector<size_t>& labelArray,
00101 const std::vector< std::list<size_t> >& neighborsVector)
00102 {
00103
00104
00105
00106 if(labelArray[node] <= label) {
00107 return false;
00108 }
00109 labelArray[node] = label;
00110
00111
00112 std::list<size_t> nodeList;
00113 std::copy(neighborsVector[node].begin(),
00114 neighborsVector[node].end(),
00115 std::back_inserter(nodeList));
00116
00117
00118 std::list<size_t>::iterator nextNodeIterator = nodeList.begin();
00119 while(nextNodeIterator != nodeList.end()) {
00120
00121 if(labelArray[*nextNodeIterator] <= label) {
00122 ++nextNodeIterator;
00123 continue;
00124 }
00125
00126
00127
00128 labelArray[*nextNodeIterator] = label;
00129 std::copy(neighborsVector[*nextNodeIterator].begin(),
00130 neighborsVector[*nextNodeIterator].end(),
00131 std::back_inserter(nodeList));
00132 ++nextNodeIterator;
00133 }
00134 return true;
00135 }
00136
00137 }
00139
00140
00141
00142
00143 template<ImageFormat FORMAT_OUT, ImageFormat FORMAT_IN>
00144 Image<FORMAT_OUT>
00145 connectedComponents(const Image<FORMAT_IN>& inputImage)
00146 {
00147 size_t numberOfComponents;
00148 return connectedComponents<FORMAT_OUT>(inputImage, numberOfComponents);
00149 }
00150
00151
00152
00153
00154 template<ImageFormat FORMAT_OUT, ImageFormat FORMAT_IN>
00155 Image<FORMAT_OUT>
00156 connectedComponents(const Image<FORMAT_IN>& inputImage,
00157 size_t& numberOfComponents)
00158 {
00159 typedef typename Image<FORMAT_IN>::const_iterator InIterator;
00160 typedef typename Image<FORMAT_OUT>::iterator OutIterator;
00161 typedef Array2D<size_t>::iterator LabelIterator;
00162
00163 Image<FORMAT_OUT> outputImage(inputImage.rows(), inputImage.columns());
00164 Array2D<size_t> labelImage(inputImage.rows(), inputImage.columns());
00165 size_t currentLabel = 0;
00166
00167
00168
00169 bool isActive = false;
00170
00171
00172
00173 InIterator inIter = inputImage.begin();
00174 LabelIterator labelIter = labelImage.begin();
00175
00176
00177 for(size_t columnIndex = 0; columnIndex < inputImage.columns();
00178 ++columnIndex) {
00179 if(*inIter) {
00180
00181 if(!isActive) {
00182
00183
00184 ++currentLabel;
00185 isActive = true;
00186 }
00187
00188 *labelIter = currentLabel;
00189 } else {
00190
00191 *labelIter = 0;
00192 isActive = false;
00193 }
00194
00195 ++inIter;
00196 ++labelIter;
00197 }
00198
00199
00200 std::vector< std::pair<size_t, size_t> > correspondences;
00201 LabelIterator chaseIter = labelImage.begin();
00202 size_t workingLabel = 0;
00203 size_t previousParentLabel = 0;
00204 for(size_t rowIndex = 1; rowIndex < inputImage.rows(); ++rowIndex) {
00205
00206
00207 isActive = false;
00208 for(size_t columnIndex = 0; columnIndex < inputImage.columns();
00209 ++columnIndex) {
00210 if(*inIter) {
00211
00212
00213
00214 size_t parentLabel = *chaseIter;
00215 if(!isActive) {
00216
00217
00218 if((parentLabel != 0)) {
00219
00220
00221 workingLabel = parentLabel;
00222 previousParentLabel = parentLabel;
00223 } else {
00224
00225
00226 ++currentLabel;
00227 workingLabel = currentLabel;
00228 previousParentLabel = 0;
00229 }
00230 isActive = true;
00231 } else {
00232
00233 if((parentLabel != 0)
00234 && (parentLabel != previousParentLabel)) {
00235
00236
00237
00238 correspondences.push_back(
00239 std::make_pair(parentLabel, workingLabel));
00240 previousParentLabel = parentLabel;
00241 }
00242 }
00243
00244 *labelIter = workingLabel;
00245 } else {
00246
00247 *labelIter = 0;
00248 isActive = false;
00249 }
00250
00251 ++inIter;
00252 ++labelIter;
00253 ++chaseIter;
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 std::vector<size_t> labelArray(currentLabel + 1);
00264 for(size_t label = 0; label < labelArray.size(); ++label) {
00265 labelArray[label] = currentLabel + 1;
00266 }
00267
00268
00269
00270
00271 typedef std::vector< std::pair<size_t, size_t> >::const_iterator
00272 CorrespondenceIterator;
00273 std::vector< std::list<size_t> > neighborsVector(labelArray.size());
00274 CorrespondenceIterator cIter = correspondences.begin();
00275 while(cIter != correspondences.end()) {
00276 neighborsVector[cIter->first].push_back(cIter->second);
00277 neighborsVector[cIter->second].push_back(cIter->first);
00278 ++cIter;
00279 }
00280
00281
00282 currentLabel = 0;
00283 for(size_t node = 0; node < labelArray.size(); ++node) {
00284 if(privateCode::propagateLabel(
00285 currentLabel, node, labelArray, neighborsVector)) {
00286 ++currentLabel;
00287 }
00288 }
00289
00290
00291 labelIter = labelImage.begin();
00292 OutIterator outIter = outputImage.begin();
00293 while(labelIter != labelImage.end()) {
00294 *outIter = static_cast<typename ImageFormatTraits<FORMAT_OUT>::PixelType>(labelArray[*labelIter]);
00295 ++outIter;
00296 ++labelIter;
00297 }
00298
00299 if(currentLabel != 0) {
00300 numberOfComponents = currentLabel - 1;
00301 } else {
00302 numberOfComponents = 0;
00303 }
00304
00305 return outputImage;
00306 }
00307
00308 }
00309
00310 }
00311
00312 #endif