largest.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Mårten Björkman (celle@csc.kth.se) 
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are
00007  * met:
00008  *
00009  *  1.Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  *  2.Redistributions in binary form must reproduce the above
00012  *    copyright notice, this list of conditions and the following
00013  *    disclaimer in the documentation and/or other materials provided
00014  *    with the distribution.  
00015  *  3.The name of Mårten Björkman may not be used to endorse or
00016  *    promote products derived from this software without specific
00017  *    prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include <vector>
00033 #include <xmmintrin.h>
00034 #include "largest.h"
00038 
00039 struct Cluster {
00041   int area;
00043   short minx;
00045   short maxx;
00047   short miny;
00049   short maxy;
00050 };
00051 
00053 
00061 int FindConnectedComponents(std::vector<short> &equivTable, int maxClusters, 
00062                             Image<unsigned char> &limg, 
00063                             Image<short> &comp, int label)
00064 {
00065   int w = limg.GetWidth();
00066   int h = limg.GetHeight();
00067   equivTable.resize(maxClusters);
00068   unsigned char *imgd = limg.GetData();
00069   short *comd = comp.GetData();
00070   int maxCompVal = maxClusters - 1;
00071   for (int i=0;i<maxClusters;i++)
00072     equivTable[i] = i;
00073   short currComp = 1;
00074   //======== very first for (0,0)
00075   if (imgd[0]==label) {
00076     equivTable[currComp] = currComp;
00077     comd[0] = currComp++;
00078     if (currComp>maxCompVal)
00079       currComp = maxCompVal;
00080   } else
00081     comd[0] = 0;
00082   //======== first line y=0
00083   for (int x=1;x<w;x++) {
00084     int indx = x - 1;
00085     bool ison = (imgd[x]==label);
00086     if (ison && comd[indx]!=0) {
00087       comd[x] = comd[indx];
00088     } else if (ison) {
00089       comd[x] = currComp++;
00090       if (currComp>maxCompVal)
00091         currComp = maxCompVal;
00092     } else
00093       comd[x] = 0;
00094   }
00095   //======== then lines y=1..height-1
00096   for (int y=1;y<h;y++) {
00097     int indy = y*w - w;
00098     bool ison = (imgd[y*w]==label);      // first x=0
00099     if (ison && comd[indy]!=0) {
00100       comd[y*w] = comd[indy];
00101     } else if (ison) {
00102       comd[y*w] = currComp++;
00103       if (currComp>maxCompVal)
00104         currComp = maxCompVal;
00105     } else
00106       comd[y*w] = 0;
00107     short last = comd[y*w];
00108     for (int x=1;x<8;x++) {  // then x=1...8
00109       int p = y*w + x;
00110       short compx = equivTable[last];
00111       short compy = equivTable[comd[p-w]];
00112       last = 0;
00113       if (imgd[p]==label) {  
00114         if (compx!=0) {
00115           last = compx;
00116           if (compy!=0 && compx!=compy) {
00117             if (compx>compy)
00118               equivTable[compx] = compy;
00119             else
00120               equivTable[compy] = compx;
00121           }
00122         } else if (compy!=0)
00123           last = compy;
00124         else {
00125           last = currComp++;
00126           if (currComp>maxCompVal)
00127             currComp = maxCompVal;
00128         }
00129       } 
00130       comd[p] = last;
00131     }
00132     unsigned char *irow = &imgd[y*w];
00133     for (int x=8;x<w;x+=8) {  // then x=8...w-1
00134       int p = y*w + x;
00135 #ifdef __SSE__
00136       __m64 zero = _mm_setzero_si64();
00137       __m64 *pos = (__m64*)&irow[x];
00138       if (_mm_movemask_pi8(_mm_cmpeq_pi8(pos[0], zero))==0xff) {
00139         __m64 *cpos = (__m64*)&comd[p];
00140         cpos[0] = zero;
00141         cpos[1] = zero;
00142         continue;
00143       }
00144 #endif
00145       short last = comd[p-1];
00146       for (int i=0;i<8;i++,p++) {
00147         short compx = equivTable[last];
00148         short compy = equivTable[comd[p-w]];
00149         last = 0;
00150         if (irow[x+i]==label) {  
00151           if (compx!=0) {
00152             last = compx;
00153             if (compy!=0) {
00154               if (compx!=compy) {
00155                 if (compx>compy)
00156                   equivTable[compx] = compy;
00157                 else
00158                   equivTable[compy] = compx;
00159               }
00160             }
00161           } else if (compy!=0)
00162             last = compy;
00163           else {
00164             last = currComp++;
00165             if (currComp>maxCompVal)
00166               currComp = maxCompVal;
00167           }
00168         } 
00169         comd[p] = last;
00170       }
00171     }
00172   }
00173   for (short i=0;i<currComp;i++) {
00174     int eq = equivTable[i];
00175     while (eq!=equivTable[eq])
00176       eq = equivTable[eq];
00177     equivTable[i] = eq;
00178   }
00179   int numClusters = 0;
00180   for (short i=0;i<currComp;i++) {
00181     int eq = equivTable[i];
00182     if (eq==i)
00183       equivTable[i] = numClusters++;
00184     else
00185       equivTable[i] = equivTable[eq];
00186   }
00187 #if 0
00188   for (short i=0;i<currComp;i++)
00189     printf("equiv[%i] = %d\r\n", i, equivTable[i]);
00190 #endif
00191 #ifdef __SSE__
00192   _mm_empty();
00193 #endif
00194   return numClusters;
00195 }  
00196 
00198 
00204 void Relabel(Image<short> &comp, std::vector<short> &equivTable, int numClusters, std::vector<Cluster> &clusters)
00205 {
00206   int width = comp.GetWidth();
00207   int height = comp.GetHeight();
00208   short *comd = comp.GetData();
00209   int w = width;
00210   int h = height;
00211   int num = numClusters;
00212   clusters.resize(numClusters);
00213   for (int i=0;i<num;i++) {
00214     clusters[i].area = 0;
00215     clusters[i].minx = 0x7fff;
00216     clusters[i].maxx = 0;
00217     clusters[i].miny = 0x7fff;
00218     clusters[i].maxy = 0;
00219   }
00220 #ifdef __SSE__
00221   __m64 zero = _mm_setzero_si64();
00222   for (int y=0;y<h;y++) {       
00223     for (int x=0;x<w;x+=4) {
00224       int k = y*w + x;  
00225       __m64 *comp4 = (__m64*)&comd[k];
00226       const __m64 c4 = *comp4;
00227       if ((_mm_movemask_pi8(_m_pcmpeqw(zero, c4))&0xaa)!=0xaa) {
00228         const __m64 c1 = _mm_set1_pi16(comd[k]); 
00229         if ((_mm_movemask_pi8(_m_pcmpeqw(c1, c4))&0xaa)==0xaa) {
00230           short val = equivTable[comd[k]];
00231           int j = val - 1;
00232           *comp4 = _mm_set1_pi16(val);
00233           Cluster &cl = clusters[j];
00234           cl.area += 4;
00235           cl.maxy = y;
00236           if (y<cl.miny) cl.miny = y;
00237           if (x<cl.minx) cl.minx = x;
00238           if (x>cl.maxx-3) cl.maxx = x + 3;
00239         } else {
00240           for (int i=0;i<4;i++) {
00241             if (comd[i+k]!=0) {
00242               short val = equivTable[comd[i+k]];
00243               int j = val - 1;
00244               comd[i+k] = val;
00245               Cluster &cl = clusters[j];
00246               cl.area++;
00247               cl.maxy = y;
00248               if (y<cl.miny) cl.miny = y;
00249               if (x<cl.minx) cl.minx = x;
00250               if (x>cl.maxx) cl.maxx = x;
00251             }
00252           }
00253         }
00254       }
00255     }
00256   }
00257   _mm_empty();
00258 #else
00259   for (int y=0;y<h;y++) {
00260     for (int x=0;x<w;x++) {
00261       int i = y*w + x;
00262       if (comd[i]!=0) {
00263         short val = equivTable[comd[i]];
00264         comd[i] = val;
00265         Cluster &cl = clusters[val-1];
00266         cl.area++;
00267         cl.maxy = y;
00268         if (y<cl.miny) cl.miny = y;
00269         if (x<cl.minx) cl.minx = x;
00270         if (x>cl.maxx) cl.maxx = x;
00271       }
00272     }
00273   }
00274 #endif 
00275 }
00276 
00277 
00278 void KeepLargestSegment(Image<unsigned char> &segment, 
00279                         int fromLabel, int toLabel, int minArea)
00280 {
00281   int width = segment.GetWidth();
00282   int height = segment.GetHeight();
00283   std::vector<short> equivTable;
00284   Image<short> components(width, height);
00285   int numClusters = FindConnectedComponents(equivTable, 4096, 
00286                                             segment, components, fromLabel);
00287   std::vector<Cluster> clusters;
00288   Relabel(components, equivTable, numClusters, clusters);
00289   if (!clusters.size())
00290     return;
00291   unsigned char *segd = segment.GetData();
00292   short *comd = components.GetData();
00293   if (minArea==0) {
00294     int maxSize = 0;
00295     int maxCluster = 0;
00296     for (unsigned int i=0;i<clusters.size();i++) {
00297       if (clusters[i].area>maxSize) {
00298         maxSize = clusters[i].area;
00299         maxCluster = i;
00300       }
00301     }
00302     assert(segment.GetHeight() == height);
00303     assert(components.GetHeight() == height);
00304     maxCluster ++;
00305     if (maxSize<100)
00306       maxCluster = -1;
00307     for (int i=0;i<width*height;i++) 
00308       if (segd[i]==fromLabel && comd[i]!=maxCluster) 
00309         segd[i] = toLabel;
00310   } else {
00311     for (int i=0;i<width*height;i++) 
00312       if (segd[i]==fromLabel && clusters[comd[i]-1].area<minArea) 
00313         segd[i] = toLabel;
00314   }
00315 }
00316 
00317 


active_realtime_segmentation
Author(s): Mårten Björkman. Maintained by Jeannette Bohg
autogenerated on Fri Jan 3 2014 12:02:50