头文件SLIC.h

  1 // SLIC.h: interface for the SLIC class.
  2 //===========================================================================
  3 // This code implements the superpixel method described in:
  4 //
  5 // Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk,
  6 // "SLIC Superpixels",
  7 // EPFL Technical Report no. 149300, June 2010.
  8 //===========================================================================
  9 //    Copyright (c) 2012 Radhakrishna Achanta [EPFL]. All rights reserved.
 10 //===========================================================================
 11 //////////////////////////////////////////////////////////////////////
 12 
 13 #if !defined(_SLIC_H_INCLUDED_)
 14 #define _SLIC_H_INCLUDED_
 15 
 16 
 17 #include <vector>
 18 #include <string>
 19 #include <algorithm>
 20 using namespace std;
 21 
 22 
 23 class SLIC  
 24 {
 25 public:
 26     SLIC();
 27     virtual ~SLIC();
 28     //============================================================================
 29     // Superpixel segmentation for a given step size (superpixel size ~= step*step)
 30     //============================================================================
 31         void DoSuperpixelSegmentation_ForGivenSuperpixelSize(
 32         const unsigned int*                            ubuff,//Each 32 bit unsigned int contains ARGB pixel values.
 33         const int                    width,
 34         const int                    height,
 35         int*&                        klabels,
 36         int&                        numlabels,
 37                 const int&                    superpixelsize,
 38                 const double&                                   compactness);
 39     //============================================================================
 40     // Superpixel segmentation for a given number of superpixels
 41     //============================================================================
 42         void DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(
 43         const unsigned int*                             ubuff,
 44         const int                    width,
 45         const int                    height,
 46         int*&                        klabels,
 47         int&                        numlabels,
 48                 const int&                    K,//required number of superpixels
 49                 const double&                                   compactness);//10-20 is a good value for CIELAB space
 50     //============================================================================
 51     // Supervoxel segmentation for a given step size (supervoxel size ~= step*step*step)
 52     //============================================================================
 53     void DoSupervoxelSegmentation(
 54         unsigned int**&        ubuffvec,
 55         const int&                    width,
 56         const int&                    height,
 57         const int&                    depth,
 58         int**&                        klabels,
 59         int&                        numlabels,
 60                 const int&                    supervoxelsize,
 61                 const double&                                   compactness);
 62     //============================================================================
 63     // Save superpixel labels in a text file in raster scan order
 64     //============================================================================
 65     void SaveSuperpixelLabels(
 66         const int*&                    labels,
 67         const int&                    width,
 68         const int&                    height,
 69         const string&                filename,
 70         const string&                path);
 71     //============================================================================
 72     // Save supervoxel labels in a text file in raster scan, depth order
 73     //============================================================================
 74     void SaveSupervoxelLabels(
 75         const int**&                labels,
 76         const int&                    width,
 77         const int&                    height,
 78         const int&                    depth,
 79         const string&                filename,
 80         const string&                path);
 81     //============================================================================
 82     // Function to draw boundaries around superpixels of a given 'color'.
 83     // Can also be used to draw boundaries around supervoxels, i.e layer by layer.
 84     //============================================================================
 85     void DrawContoursAroundSegments(
 86         unsigned int*&                segmentedImage,
 87         int*&                        labels,
 88         const int&                    width,
 89         const int&                    height,
 90         const unsigned int&            color );
 91 
 92 private:
 93     //============================================================================
 94     // The main SLIC algorithm for generating superpixels
 95     //============================================================================
 96     void PerformSuperpixelSLIC(
 97         vector<double>&                kseedsl,
 98         vector<double>&                kseedsa,
 99         vector<double>&                kseedsb,
100         vector<double>&                kseedsx,
101         vector<double>&                kseedsy,
102         int*&                        klabels,
103         const int&                    STEP,
104                 const vector<double>&        edgemag,
105         const double&                m = 10.0);
106     //============================================================================
107     // The main SLIC algorithm for generating supervoxels
108     //============================================================================
109     void PerformSupervoxelSLIC(
110         vector<double>&                kseedsl,
111         vector<double>&                kseedsa,
112         vector<double>&                kseedsb,
113         vector<double>&                kseedsx,
114         vector<double>&                kseedsy,
115         vector<double>&                kseedsz,
116         int**&                        klabels,
117         const int&                    STEP,
118         const double&                compactness);
119     //============================================================================
120     // Pick seeds for superpixels when step size of superpixels is given.
121     //============================================================================
122     void GetLABXYSeeds_ForGivenStepSize(
123         vector<double>&                kseedsl,
124         vector<double>&                kseedsa,
125         vector<double>&                kseedsb,
126         vector<double>&                kseedsx,
127         vector<double>&                kseedsy,
128         const int&                    STEP,
129         const bool&                    perturbseeds,
130         const vector<double>&        edgemag);
131     //============================================================================
132     // Pick seeds for supervoxels
133     //============================================================================
134     void GetKValues_LABXYZ(
135         vector<double>&                kseedsl,
136         vector<double>&                kseedsa,
137         vector<double>&                kseedsb,
138         vector<double>&                kseedsx,
139         vector<double>&                kseedsy,
140         vector<double>&                kseedsz,
141         const int&                    STEP);
142     //============================================================================
143     // Move the superpixel seeds to low gradient positions to avoid putting seeds
144     // at region boundaries.
145     //============================================================================
146     void PerturbSeeds(
147         vector<double>&                kseedsl,
148         vector<double>&                kseedsa,
149         vector<double>&                kseedsb,
150         vector<double>&                kseedsx,
151         vector<double>&                kseedsy,
152         const vector<double>&        edges);
153     //============================================================================
154     // Detect color edges, to help PerturbSeeds()
155     //============================================================================
156     void DetectLabEdges(
157         const double*                lvec,
158         const double*                avec,
159         const double*                bvec,
160         const int&                    width,
161         const int&                    height,
162         vector<double>&                edges);
163     //============================================================================
164     // sRGB to XYZ conversion; helper for RGB2LAB()
165     //============================================================================
166     void RGB2XYZ(
167         const int&                    sR,
168         const int&                    sG,
169         const int&                    sB,
170         double&                        X,
171         double&                        Y,
172         double&                        Z);
173     //============================================================================
174     // sRGB to CIELAB conversion (uses RGB2XYZ function)
175     //============================================================================
176     void RGB2LAB(
177         const int&                    sR,
178         const int&                    sG,
179         const int&                    sB,
180         double&                        lval,
181         double&                        aval,
182         double&                        bval);
183     //============================================================================
184     // sRGB to CIELAB conversion for 2-D images
185     //============================================================================
186     void DoRGBtoLABConversion(
187         const unsigned int*&        ubuff,
188         double*&                    lvec,
189         double*&                    avec,
190         double*&                    bvec);
191     //============================================================================
192     // sRGB to CIELAB conversion for 3-D volumes
193     //============================================================================
194     void DoRGBtoLABConversion(
195         unsigned int**&                ubuff,
196         double**&                    lvec,
197         double**&                    avec,
198         double**&                    bvec);
199     //============================================================================
200     // Post-processing of SLIC segmentation, to avoid stray labels.
201     //============================================================================
202     void EnforceLabelConnectivity(
203         const int*                    labels,
204         const int                    width,
205         const int                    height,
206         int*&                        nlabels,//input labels that need to be corrected to remove stray labels
207         int&                        numlabels,//the number of labels changes in the end if segments are removed
208         const int&                    K); //the number of superpixels desired by the user
209     //============================================================================
210     // Post-processing of SLIC supervoxel segmentation, to avoid stray labels.
211     //============================================================================
212     void EnforceSupervoxelLabelConnectivity(
213         int**&                        labels,//input - previous labels, output - new labels
214         const int&                    width,
215         const int&                    height,
216         const int&                    depth,
217         int&                        numlabels,
218         const int&                    STEP);
219 
220 private:
221     int                                        m_width;
222     int                                        m_height;
223     int                                        m_depth;
224 
225     double*                                    m_lvec;
226     double*                                    m_avec;
227     double*                                    m_bvec;
228 
229     double**                                m_lvecvec;
230     double**                                m_avecvec;
231     double**                                m_bvecvec;
232 };
233 
234 #endif // !defined(_SLIC_H_INCLUDED_)

源文件SLIC.cpp

   1 // SLIC.cpp: implementation of the SLIC class.
   2 //
   3 // Copyright (C) Radhakrishna Achanta 2012
   4 // All rights reserved
   5 // Email: firstname.lastname@epfl.ch
   6 //////////////////////////////////////////////////////////////////////
   7 //#include "stdafx.h"
   8 #include <cfloat>
   9 #include <cmath>
  10 #include <iostream>
  11 #include <fstream>
  12 #include "SLIC.h"
  13 
  14 
  15 //////////////////////////////////////////////////////////////////////
  16 // Construction/Destruction
  17 //////////////////////////////////////////////////////////////////////
  18 
  19 SLIC::SLIC()
  20 {
  21     m_lvec = NULL;
  22     m_avec = NULL;
  23     m_bvec = NULL;
  24 
  25     m_lvecvec = NULL;
  26     m_avecvec = NULL;
  27     m_bvecvec = NULL;
  28 }
  29 
  30 SLIC::~SLIC()
  31 {
  32     if(m_lvec) delete [] m_lvec;
  33     if(m_avec) delete [] m_avec;
  34     if(m_bvec) delete [] m_bvec;
  35 
  36 
  37     if(m_lvecvec)
  38     {
  39         for( int d = 0; d < m_depth; d++ ) delete [] m_lvecvec[d];
  40         delete [] m_lvecvec;
  41     }
  42     if(m_avecvec)
  43     {
  44         for( int d = 0; d < m_depth; d++ ) delete [] m_avecvec[d];
  45         delete [] m_avecvec;
  46     }
  47     if(m_bvecvec)
  48     {
  49         for( int d = 0; d < m_depth; d++ ) delete [] m_bvecvec[d];
  50         delete [] m_bvecvec;
  51     }
  52 }
  53 
  54 //==============================================================================
  55 ///    RGB2XYZ
  56 ///
  57 /// sRGB (D65 illuninant assumption) to XYZ conversion
  58 //==============================================================================
  59 void SLIC::RGB2XYZ(
  60     const int&        sR,
  61     const int&        sG,
  62     const int&        sB,
  63     double&            X,
  64     double&            Y,
  65     double&            Z)
  66 {
  67     double R = sR/255.0;
  68     double G = sG/255.0;
  69     double B = sB/255.0;
  70 
  71     double r, g, b;
  72 
  73     if(R <= 0.04045)    r = R/12.92;
  74     else                r = pow((R+0.055)/1.055,2.4);
  75     if(G <= 0.04045)    g = G/12.92;
  76     else                g = pow((G+0.055)/1.055,2.4);
  77     if(B <= 0.04045)    b = B/12.92;
  78     else                b = pow((B+0.055)/1.055,2.4);
  79 
  80     X = r*0.4124564 + g*0.3575761 + b*0.1804375;
  81     Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
  82     Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
  83 }
  84 
  85 //===========================================================================
  86 ///    RGB2LAB
  87 //===========================================================================
  88 void SLIC::RGB2LAB(const int& sR, const int& sG, const int& sB, double& lval, double& aval, double& bval)
  89 {
  90     //------------------------
  91     // sRGB to XYZ conversion
  92     //------------------------
  93     double X, Y, Z;
  94     RGB2XYZ(sR, sG, sB, X, Y, Z);
  95 
  96     //------------------------
  97     // XYZ to LAB conversion
  98     //------------------------
  99     double epsilon = 0.008856;    //actual CIE standard
 100     double kappa   = 903.3;        //actual CIE standard
 101 
 102     double Xr = 0.950456;    //reference white
 103     double Yr = 1.0;        //reference white
 104     double Zr = 1.088754;    //reference white
 105 
 106     double xr = X/Xr;
 107     double yr = Y/Yr;
 108     double zr = Z/Zr;
 109 
 110     double fx, fy, fz;
 111     if(xr > epsilon)    fx = pow(xr, 1.0/3.0);
 112     else                fx = (kappa*xr + 16.0)/116.0;
 113     if(yr > epsilon)    fy = pow(yr, 1.0/3.0);
 114     else                fy = (kappa*yr + 16.0)/116.0;
 115     if(zr > epsilon)    fz = pow(zr, 1.0/3.0);
 116     else                fz = (kappa*zr + 16.0)/116.0;
 117 
 118     lval = 116.0*fy-16.0;
 119     aval = 500.0*(fx-fy);
 120     bval = 200.0*(fy-fz);
 121 }
 122 
 123 //===========================================================================
 124 ///    DoRGBtoLABConversion
 125 ///
 126 ///    For whole image: overlaoded floating point version
 127 //===========================================================================
 128 void SLIC::DoRGBtoLABConversion(
 129     const unsigned int*&        ubuff,
 130     double*&                    lvec,
 131     double*&                    avec,
 132     double*&                    bvec)
 133 {
 134     int sz = m_width*m_height;
 135     lvec = new double[sz];
 136     avec = new double[sz];
 137     bvec = new double[sz];
 138 
 139     for( int j = 0; j < sz; j++ )
 140     {
 141         int r = (ubuff[j] >> 16) & 0xFF;
 142         int g = (ubuff[j] >>  8) & 0xFF;
 143         int b = (ubuff[j]      ) & 0xFF;
 144 
 145         RGB2LAB( r, g, b, lvec[j], avec[j], bvec[j] );
 146     }
 147 }
 148 
 149 //===========================================================================
 150 ///    DoRGBtoLABConversion
 151 ///
 152 /// For whole volume
 153 //===========================================================================
 154 void SLIC::DoRGBtoLABConversion(
 155     unsigned int**&        ubuff,
 156     double**&                    lvec,
 157     double**&                    avec,
 158     double**&                    bvec)
 159 {
 160     int sz = m_width*m_height;
 161     for( int d = 0; d < m_depth; d++ )
 162     {
 163         for( int j = 0; j < sz; j++ )
 164         {
 165             int r = (ubuff[d][j] >> 16) & 0xFF;
 166             int g = (ubuff[d][j] >>  8) & 0xFF;
 167             int b = (ubuff[d][j]      ) & 0xFF;
 168 
 169             RGB2LAB( r, g, b, lvec[d][j], avec[d][j], bvec[d][j] );
 170         }
 171     }
 172 }
 173 
 174 //=================================================================================
 175 /// DrawContoursAroundSegments
 176 ///
 177 /// Internal contour drawing option exists. One only needs to comment the if
 178 /// statement inside the loop that looks at neighbourhood.
 179 //=================================================================================
 180 void SLIC::DrawContoursAroundSegments(
 181     unsigned int*&            ubuff,
 182     int*&                    labels,
 183     const int&                width,
 184     const int&                height,
 185     const unsigned int&                color )
 186 {
 187     const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
 188     const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
 189 
 190 /*    int sz = width*height;
 191 
 192     vector<bool> istaken(sz, false);
 193 
 194     int mainindex(0);
 195     for( int j = 0; j < height; j++ )
 196     {
 197         for( int k = 0; k < width; k++ )
 198         {
 199             int np(0);
 200             for( int i = 0; i < 8; i++ )
 201             {
 202                 int x = k + dx8[i];
 203                 int y = j + dy8[i];
 204 
 205                 if( (x >= 0 && x < width) && (y >= 0 && y < height) )
 206                 {
 207                     int index = y*width + x;
 208 
 209                     if( false == istaken[index] )//comment this to obtain internal contours
 210                     {
 211                         if( labels[mainindex] != labels[index] ) np++;
 212                     }
 213                 }
 214             }
 215             if( np > 1 )//change to 2 or 3 for thinner lines
 216             {
 217                 ubuff[mainindex] = color;
 218                 istaken[mainindex] = true;
 219             }
 220             mainindex++;
 221         }
 222     }*/
 223 
 224 
 225     int sz = width*height;
 226     vector<bool> istaken(sz, false);
 227     vector<int> contourx(sz);vector<int> contoury(sz);
 228     int mainindex(0);int cind(0);
 229     for( int j = 0; j < height; j++ )
 230     {
 231         for( int k = 0; k < width; k++ )
 232         {
 233             int np(0);
 234             for( int i = 0; i < 8; i++ )
 235             {
 236                 int x = k + dx8[i];
 237                 int y = j + dy8[i];
 238 
 239                 if( (x >= 0 && x < width) && (y >= 0 && y < height) )
 240                 {
 241                     int index = y*width + x;
 242 
 243                     //if( false == istaken[index] )//comment this to obtain internal contours
 244                     {
 245                         if( labels[mainindex] != labels[index] ) np++;
 246                     }
 247                 }
 248             }
 249             if( np > 1 )
 250             {
 251                 contourx[cind] = k;
 252                 contoury[cind] = j;
 253                 istaken[mainindex] = true;
 254                 //img[mainindex] = color;
 255                 cind++;
 256             }
 257             mainindex++;
 258         }
 259     }
 260 
 261     int numboundpix = cind;//int(contourx.size());
 262     for( int j = 0; j < numboundpix; j++ )
 263     {
 264         int ii = contoury[j]*width + contourx[j];
 265         ubuff[ii] = 0xffffff;
 266 
 267         for( int n = 0; n < 8; n++ )
 268         {
 269             int x = contourx[j] + dx8[n];
 270             int y = contoury[j] + dy8[n];
 271             if( (x >= 0 && x < width) && (y >= 0 && y < height) )
 272             {
 273                 int ind = y*width + x;
 274                 if(!istaken[ind]) ubuff[ind] = 0;
 275             }
 276         }
 277     }
 278 }
 279 
 280 
 281 //==============================================================================
 282 ///    DetectLabEdges
 283 //==============================================================================
 284 void SLIC::DetectLabEdges(
 285     const double*                lvec,
 286     const double*                avec,
 287     const double*                bvec,
 288     const int&                    width,
 289     const int&                    height,
 290     vector<double>&                edges)
 291 {
 292     int sz = width*height;
 293 
 294     edges.resize(sz,0);
 295     for( int j = 1; j < height-1; j++ )
 296     {
 297         for( int k = 1; k < width-1; k++ )
 298         {
 299             int i = j*width+k;
 300 
 301             double dx = (lvec[i-1]-lvec[i+1])*(lvec[i-1]-lvec[i+1]) +
 302                         (avec[i-1]-avec[i+1])*(avec[i-1]-avec[i+1]) +
 303                         (bvec[i-1]-bvec[i+1])*(bvec[i-1]-bvec[i+1]);
 304 
 305             double dy = (lvec[i-width]-lvec[i+width])*(lvec[i-width]-lvec[i+width]) +
 306                         (avec[i-width]-avec[i+width])*(avec[i-width]-avec[i+width]) +
 307                         (bvec[i-width]-bvec[i+width])*(bvec[i-width]-bvec[i+width]);
 308 
 309             //edges[i] = fabs(dx) + fabs(dy);
 310             edges[i] = dx*dx + dy*dy;
 311         }
 312     }
 313 }
 314 
 315 //===========================================================================
 316 ///    PerturbSeeds
 317 //===========================================================================
 318 void SLIC::PerturbSeeds(
 319     vector<double>&                kseedsl,
 320     vector<double>&                kseedsa,
 321     vector<double>&                kseedsb,
 322     vector<double>&                kseedsx,
 323     vector<double>&                kseedsy,
 324         const vector<double>&                   edges)
 325 {
 326     const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
 327     const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
 328     
 329     int numseeds = kseedsl.size();
 330 
 331     for( int n = 0; n < numseeds; n++ )
 332     {
 333         int ox = kseedsx[n];//original x
 334         int oy = kseedsy[n];//original y
 335         int oind = oy*m_width + ox;
 336 
 337         int storeind = oind;
 338         for( int i = 0; i < 8; i++ )
 339         {
 340             int nx = ox+dx8[i];//new x
 341             int ny = oy+dy8[i];//new y
 342 
 343             if( nx >= 0 && nx < m_width && ny >= 0 && ny < m_height)
 344             {
 345                 int nind = ny*m_width + nx;
 346                 if( edges[nind] < edges[storeind])
 347                 {
 348                     storeind = nind;
 349                 }
 350             }
 351         }
 352         if(storeind != oind)
 353         {
 354             kseedsx[n] = storeind%m_width;
 355             kseedsy[n] = storeind/m_width;
 356             kseedsl[n] = m_lvec[storeind];
 357             kseedsa[n] = m_avec[storeind];
 358             kseedsb[n] = m_bvec[storeind];
 359         }
 360     }
 361 }
 362 
 363 
 364 //===========================================================================
 365 ///    GetLABXYSeeds_ForGivenStepSize
 366 ///
 367 /// The k seed values are taken as uniform spatial pixel samples.
 368 //===========================================================================
 369 void SLIC::GetLABXYSeeds_ForGivenStepSize(
 370     vector<double>&                kseedsl,
 371     vector<double>&                kseedsa,
 372     vector<double>&                kseedsb,
 373     vector<double>&                kseedsx,
 374     vector<double>&                kseedsy,
 375     const int&                    STEP,
 376     const bool&                    perturbseeds,
 377     const vector<double>&       edgemag)
 378 {
 379     const bool hexgrid = false;
 380     int numseeds(0);
 381     int n(0);
 382 
 383     //int xstrips = m_width/STEP;
 384     //int ystrips = m_height/STEP;
 385     int xstrips = (0.5+double(m_width)/double(STEP));
 386     int ystrips = (0.5+double(m_height)/double(STEP));
 387 
 388     int xerr = m_width  - STEP*xstrips;if(xerr < 0){xstrips--;xerr = m_width - STEP*xstrips;}
 389     int yerr = m_height - STEP*ystrips;if(yerr < 0){ystrips--;yerr = m_height- STEP*ystrips;}
 390 
 391     double xerrperstrip = double(xerr)/double(xstrips);
 392     double yerrperstrip = double(yerr)/double(ystrips);
 393 
 394     int xoff = STEP/2;
 395     int yoff = STEP/2;
 396     //-------------------------
 397     numseeds = xstrips*ystrips;
 398     //-------------------------
 399     kseedsl.resize(numseeds);
 400     kseedsa.resize(numseeds);
 401     kseedsb.resize(numseeds);
 402     kseedsx.resize(numseeds);
 403     kseedsy.resize(numseeds);
 404 
 405     for( int y = 0; y < ystrips; y++ )
 406     {
 407         int ye = y*yerrperstrip;
 408         for( int x = 0; x < xstrips; x++ )
 409         {
 410             int xe = x*xerrperstrip;
 411             int seedx = (x*STEP+xoff+xe);
 412             if(hexgrid){ seedx = x*STEP+(xoff<<(y&0x1))+xe; seedx = min(m_width-1,seedx); }//for hex grid sampling
 413             int seedy = (y*STEP+yoff+ye);
 414             int i = seedy*m_width + seedx;
 415             
 416             kseedsl[n] = m_lvec[i];
 417             kseedsa[n] = m_avec[i];
 418             kseedsb[n] = m_bvec[i];
 419             kseedsx[n] = seedx;
 420             kseedsy[n] = seedy;
 421             n++;
 422         }
 423     }
 424 
 425     
 426     if(perturbseeds)
 427     {
 428         PerturbSeeds(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, edgemag);
 429     }
 430 }
 431 
 432 //===========================================================================
 433 ///    GetKValues_LABXYZ
 434 ///
 435 /// The k seed values are taken as uniform spatial pixel samples.
 436 //===========================================================================
 437 void SLIC::GetKValues_LABXYZ(
 438     vector<double>&                kseedsl,
 439     vector<double>&                kseedsa,
 440     vector<double>&                kseedsb,
 441     vector<double>&                kseedsx,
 442     vector<double>&                kseedsy,
 443     vector<double>&                kseedsz,
 444         const int&                STEP)
 445 {
 446     const bool hexgrid = false;
 447     int numseeds(0);
 448     int n(0);
 449 
 450     int xstrips = (0.5+double(m_width)/double(STEP));
 451     int ystrips = (0.5+double(m_height)/double(STEP));
 452     int zstrips = (0.5+double(m_depth)/double(STEP));
 453 
 454     int xerr = m_width  - STEP*xstrips;if(xerr < 0){xstrips--;xerr = m_width - STEP*xstrips;}
 455     int yerr = m_height - STEP*ystrips;if(yerr < 0){ystrips--;yerr = m_height- STEP*ystrips;}
 456     int zerr = m_depth  - STEP*zstrips;if(zerr < 0){zstrips--;zerr = m_depth - STEP*zstrips;}
 457 
 458     double xerrperstrip = double(xerr)/double(xstrips);
 459     double yerrperstrip = double(yerr)/double(ystrips);
 460     double zerrperstrip = double(zerr)/double(zstrips);
 461 
 462     int xoff = STEP/2;
 463     int yoff = STEP/2;
 464     int zoff = STEP/2;
 465     //-------------------------
 466     numseeds = xstrips*ystrips*zstrips;
 467     //-------------------------
 468     kseedsl.resize(numseeds);
 469     kseedsa.resize(numseeds);
 470     kseedsb.resize(numseeds);
 471     kseedsx.resize(numseeds);
 472     kseedsy.resize(numseeds);
 473     kseedsz.resize(numseeds);
 474 
 475     for( int z = 0; z < zstrips; z++ )
 476     {
 477         int ze = z*zerrperstrip;
 478         int d = (z*STEP+zoff+ze);
 479         for( int y = 0; y < ystrips; y++ )
 480         {
 481             int ye = y*yerrperstrip;
 482             for( int x = 0; x < xstrips; x++ )
 483             {
 484                 int xe = x*xerrperstrip;
 485                 int i = (y*STEP+yoff+ye)*m_width + (x*STEP+xoff+xe);
 486                 
 487                 kseedsl[n] = m_lvecvec[d][i];
 488                 kseedsa[n] = m_avecvec[d][i];
 489                 kseedsb[n] = m_bvecvec[d][i];
 490                 kseedsx[n] = (x*STEP+xoff+xe);
 491                 kseedsy[n] = (y*STEP+yoff+ye);
 492                 kseedsz[n] = d;
 493                 n++;
 494             }
 495         }
 496     }
 497 }
 498 
 499 //===========================================================================
 500 ///    PerformSuperpixelSLIC
 501 ///
 502 ///    Performs k mean segmentation. It is fast because it looks locally, not
 503 /// over the entire image.
 504 //===========================================================================
 505 void SLIC::PerformSuperpixelSLIC(
 506     vector<double>&                kseedsl,
 507     vector<double>&                kseedsa,
 508     vector<double>&                kseedsb,
 509     vector<double>&                kseedsx,
 510     vector<double>&                kseedsy,
 511         int*&                    klabels,
 512         const int&                STEP,
 513         const vector<double>&                   edgemag,
 514     const double&                M)
 515 {
 516     int sz = m_width*m_height;
 517     const int numk = kseedsl.size();
 518     //----------------
 519     int offset = STEP;
 520         //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
 521     //----------------
 522     
 523     vector<double> clustersize(numk, 0);
 524     vector<double> inv(numk, 0);//to store 1/clustersize[k] values
 525 
 526     vector<double> sigmal(numk, 0);
 527     vector<double> sigmaa(numk, 0);
 528     vector<double> sigmab(numk, 0);
 529     vector<double> sigmax(numk, 0);
 530     vector<double> sigmay(numk, 0);
 531     vector<double> distvec(sz, DBL_MAX);
 532 
 533     double invwt = 1.0/((STEP/M)*(STEP/M));
 534 
 535     int x1, y1, x2, y2;
 536     double l, a, b;
 537     double dist;
 538     double distxy;
 539     for( int itr = 0; itr < 10; itr++ )
 540     {
 541         distvec.assign(sz, DBL_MAX);
 542         for( int n = 0; n < numk; n++ )
 543         {
 544                         y1 = max(0.0,            kseedsy[n]-offset);
 545                         y2 = min((double)m_height,    kseedsy[n]+offset);
 546                         x1 = max(0.0,            kseedsx[n]-offset);
 547                         x2 = min((double)m_width,    kseedsx[n]+offset);
 548 
 549 
 550             for( int y = y1; y < y2; y++ )
 551             {
 552                 for( int x = x1; x < x2; x++ )
 553                 {
 554                     int i = y*m_width + x;
 555 
 556                     l = m_lvec[i];
 557                     a = m_avec[i];
 558                     b = m_bvec[i];
 559 
 560                     dist =            (l - kseedsl[n])*(l - kseedsl[n]) +
 561                                     (a - kseedsa[n])*(a - kseedsa[n]) +
 562                                     (b - kseedsb[n])*(b - kseedsb[n]);
 563 
 564                     distxy =        (x - kseedsx[n])*(x - kseedsx[n]) +
 565                                     (y - kseedsy[n])*(y - kseedsy[n]);
 566                     
 567                     //------------------------------------------------------------------------
 568                     dist += distxy*invwt;//dist = sqrt(dist) + sqrt(distxy*invwt);//this is more exact
 569                     //------------------------------------------------------------------------
 570                     if( dist < distvec[i] )
 571                     {
 572                         distvec[i] = dist;
 573                         klabels[i]  = n;
 574                     }
 575                 }
 576             }
 577         }
 578         //-----------------------------------------------------------------
 579         // Recalculate the centroid and store in the seed values
 580         //-----------------------------------------------------------------
 581         //instead of reassigning memory on each iteration, just reset.
 582     
 583         sigmal.assign(numk, 0);
 584         sigmaa.assign(numk, 0);
 585         sigmab.assign(numk, 0);
 586         sigmax.assign(numk, 0);
 587         sigmay.assign(numk, 0);
 588         clustersize.assign(numk, 0);
 589         //------------------------------------
 590         //edgesum.assign(numk, 0);
 591         //------------------------------------
 592 
 593         {int ind(0);
 594         for( int r = 0; r < m_height; r++ )
 595         {
 596             for( int c = 0; c < m_width; c++ )
 597             {
 598                 sigmal[klabels[ind]] += m_lvec[ind];
 599                 sigmaa[klabels[ind]] += m_avec[ind];
 600                 sigmab[klabels[ind]] += m_bvec[ind];
 601                 sigmax[klabels[ind]] += c;
 602                 sigmay[klabels[ind]] += r;
 603                 //------------------------------------
 604                 //edgesum[klabels[ind]] += edgemag[ind];
 605                 //------------------------------------
 606                 clustersize[klabels[ind]] += 1.0;
 607                 ind++;
 608             }
 609         }}
 610 
 611         {for( int k = 0; k < numk; k++ )
 612         {
 613             if( clustersize[k] <= 0 ) clustersize[k] = 1;
 614             inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
 615         }}
 616         
 617         {for( int k = 0; k < numk; k++ )
 618         {
 619             kseedsl[k] = sigmal[k]*inv[k];
 620             kseedsa[k] = sigmaa[k]*inv[k];
 621             kseedsb[k] = sigmab[k]*inv[k];
 622             kseedsx[k] = sigmax[k]*inv[k];
 623             kseedsy[k] = sigmay[k]*inv[k];
 624             //------------------------------------
 625             //edgesum[k] *= inv[k];
 626             //------------------------------------
 627         }}
 628     }
 629 }
 630 
 631 //===========================================================================
 632 ///    PerformSupervoxelSLIC
 633 ///
 634 ///    Performs k mean segmentation. It is fast because it searches locally, not
 635 /// over the entire image.
 636 //===========================================================================
 637 void SLIC::PerformSupervoxelSLIC(
 638     vector<double>&                kseedsl,
 639     vector<double>&                kseedsa,
 640     vector<double>&                kseedsb,
 641     vector<double>&                kseedsx,
 642     vector<double>&                kseedsy,
 643     vector<double>&                kseedsz,
 644         int**&                    klabels,
 645         const int&                STEP,
 646     const double&                compactness)
 647 {
 648     int sz = m_width*m_height;
 649     const int numk = kseedsl.size();
 650         //int numitr(0);
 651 
 652     //----------------
 653     int offset = STEP;
 654         //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
 655     //----------------
 656 
 657     vector<double> clustersize(numk, 0);
 658     vector<double> inv(numk, 0);//to store 1/clustersize[k] values
 659 
 660     vector<double> sigmal(numk, 0);
 661     vector<double> sigmaa(numk, 0);
 662     vector<double> sigmab(numk, 0);
 663     vector<double> sigmax(numk, 0);
 664     vector<double> sigmay(numk, 0);
 665     vector<double> sigmaz(numk, 0);
 666 
 667     vector< double > initdouble(sz, DBL_MAX);
 668     vector< vector<double> > distvec(m_depth, initdouble);
 669     //vector<double> distvec(sz, DBL_MAX);
 670 
 671     double invwt = 1.0/((STEP/compactness)*(STEP/compactness));//compactness = 20.0 is usually good.
 672 
 673     int x1, y1, x2, y2, z1, z2;
 674     double l, a, b;
 675     double dist;
 676     double distxyz;
 677     for( int itr = 0; itr < 5; itr++ )
 678     {
 679         distvec.assign(m_depth, initdouble);
 680         for( int n = 0; n < numk; n++ )
 681         {
 682                         y1 = max(0.0,            kseedsy[n]-offset);
 683                         y2 = min((double)m_height,    kseedsy[n]+offset);
 684                         x1 = max(0.0,            kseedsx[n]-offset);
 685                         x2 = min((double)m_width,    kseedsx[n]+offset);
 686                         z1 = max(0.0,            kseedsz[n]-offset);
 687                         z2 = min((double)m_depth,    kseedsz[n]+offset);
 688 
 689 
 690             for( int z = z1; z < z2; z++ )
 691             {
 692                 for( int y = y1; y < y2; y++ )
 693                 {
 694                     for( int x = x1; x < x2; x++ )
 695                     {
 696                         int i = y*m_width + x;
 697 
 698                         l = m_lvecvec[z][i];
 699                         a = m_avecvec[z][i];
 700                         b = m_bvecvec[z][i];
 701 
 702                         dist =            (l - kseedsl[n])*(l - kseedsl[n]) +
 703                                         (a - kseedsa[n])*(a - kseedsa[n]) +
 704                                         (b - kseedsb[n])*(b - kseedsb[n]);
 705 
 706                         distxyz =        (x - kseedsx[n])*(x - kseedsx[n]) +
 707                                         (y - kseedsy[n])*(y - kseedsy[n]) +
 708                                         (z - kseedsz[n])*(z - kseedsz[n]);
 709                         //------------------------------------------------------------------------
 710                         dist += distxyz*invwt;
 711                         //------------------------------------------------------------------------
 712                         if( dist < distvec[z][i] )
 713                         {
 714                             distvec[z][i] = dist;
 715                             klabels[z][i]  = n;
 716                         }
 717                     }
 718                 }
 719             }
 720         }
 721         //-----------------------------------------------------------------
 722         // Recalculate the centroid and store in the seed values
 723         //-----------------------------------------------------------------
 724         //instead of reassigning memory on each iteration, just reset.
 725     
 726         sigmal.assign(numk, 0);
 727         sigmaa.assign(numk, 0);
 728         sigmab.assign(numk, 0);
 729         sigmax.assign(numk, 0);
 730         sigmay.assign(numk, 0);
 731         sigmaz.assign(numk, 0);
 732         clustersize.assign(numk, 0);
 733 
 734         for( int d = 0; d < m_depth; d++  )
 735         {
 736             int ind(0);
 737             for( int r = 0; r < m_height; r++ )
 738             {
 739                 for( int c = 0; c < m_width; c++ )
 740                 {
 741                     sigmal[klabels[d][ind]] += m_lvecvec[d][ind];
 742                     sigmaa[klabels[d][ind]] += m_avecvec[d][ind];
 743                     sigmab[klabels[d][ind]] += m_bvecvec[d][ind];
 744                     sigmax[klabels[d][ind]] += c;
 745                     sigmay[klabels[d][ind]] += r;
 746                     sigmaz[klabels[d][ind]] += d;
 747 
 748                     clustersize[klabels[d][ind]] += 1.0;
 749                     ind++;
 750                 }
 751             }
 752         }
 753 
 754         {for( int k = 0; k < numk; k++ )
 755         {
 756             if( clustersize[k] <= 0 ) clustersize[k] = 1;
 757             inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
 758         }}
 759         
 760         {for( int k = 0; k < numk; k++ )
 761         {
 762             kseedsl[k] = sigmal[k]*inv[k];
 763             kseedsa[k] = sigmaa[k]*inv[k];
 764             kseedsb[k] = sigmab[k]*inv[k];
 765             kseedsx[k] = sigmax[k]*inv[k];
 766             kseedsy[k] = sigmay[k]*inv[k];
 767             kseedsz[k] = sigmaz[k]*inv[k];
 768         }}
 769     }
 770 }
 771 
 772 
 773 //===========================================================================
 774 ///    SaveSuperpixelLabels
 775 ///
 776 ///    Save labels in raster scan order.
 777 //===========================================================================
 778 void SLIC::SaveSuperpixelLabels(
 779     const int*&                    labels,
 780     const int&                    width,
 781     const int&                    height,
 782     const string&                filename,
 783     const string&                path) 
 784 {
 785 #ifdef WINDOWS
 786         char fname[256];
 787         char extn[256];
 788         _splitpath(filename.c_str(), NULL, NULL, fname, extn);
 789         string temp = fname;
 790         string finalpath = path + temp + string(".dat");
 791 #else
 792         string nameandextension = filename;
 793         size_t pos = filename.find_last_of("/");
 794         if(pos != string::npos)//if a slash is found, then take the filename with extension
 795         {
 796             nameandextension = filename.substr(pos+1);
 797         }
 798         string newname = nameandextension.replace(nameandextension.rfind(".")+1, 3, "dat");//find the position of the dot and replace the 3 characters following it.
 799         string finalpath = path+newname;
 800 #endif
 801 
 802         int sz = width*height;
 803     ofstream outfile;
 804     outfile.open(finalpath.c_str(), ios::binary);
 805     for( int i = 0; i < sz; i++ )
 806     {
 807         outfile.write((const char*)&labels[i], sizeof(int));
 808     }
 809     outfile.close();
 810 }
 811 
 812 
 813 //===========================================================================
 814 ///    SaveSupervoxelLabels
 815 ///
 816 ///    Save labels in raster scan order.
 817 //===========================================================================
 818 void SLIC::SaveSupervoxelLabels(
 819     const int**&                labels,
 820     const int&                    width,
 821     const int&                    height,
 822     const int&                    depth,
 823     const string&                filename,
 824     const string&                path) 
 825 {
 826 #ifdef WINDOWS
 827         char fname[256];
 828         char extn[256];
 829         _splitpath(filename.c_str(), NULL, NULL, fname, extn);
 830         string temp = fname;
 831         string finalpath = path + temp + string(".dat");
 832 #else
 833         string nameandextension = filename;
 834         size_t pos = filename.find_last_of("/");
 835         if(pos != string::npos)//if a slash is found, then take the filename with extension
 836         {
 837             nameandextension = filename.substr(pos+1);
 838         }
 839         string newname = nameandextension.replace(nameandextension.rfind(".")+1, 3, "dat");//find the position of the dot and replace the 3 characters following it.
 840         string finalpath = path+newname;
 841 #endif
 842 
 843         int sz = width*height;
 844     ofstream outfile;
 845     outfile.open(finalpath.c_str(), ios::binary);
 846     for( int d = 0; d < depth; d++ )
 847     {
 848         for( int i = 0; i < sz; i++ )
 849         {
 850             outfile.write((const char*)&labels[d][i], sizeof(int));
 851         }
 852     }
 853     outfile.close();
 854 }
 855 
 856 //===========================================================================
 857 ///    EnforceLabelConnectivity
 858 ///
 859 ///        1. finding an adjacent label for each new component at the start
 860 ///        2. if a certain component is too small, assigning the previously found
 861 ///            adjacent label to this component, and not incrementing the label.
 862 //===========================================================================
 863 void SLIC::EnforceLabelConnectivity(
 864     const int*                    labels,//input labels that need to be corrected to remove stray labels
 865     const int                    width,
 866     const int                    height,
 867     int*&                        nlabels,//new labels
 868     int&                        numlabels,//the number of labels changes in the end if segments are removed
 869     const int&                    K) //the number of superpixels desired by the user
 870 {
 871 //    const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
 872 //    const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
 873 
 874     const int dx4[4] = {-1,  0,  1,  0};
 875     const int dy4[4] = { 0, -1,  0,  1};
 876 
 877     const int sz = width*height;
 878     const int SUPSZ = sz/K;
 879     //nlabels.resize(sz, -1);
 880     for( int i = 0; i < sz; i++ ) nlabels[i] = -1;
 881     int label(0);
 882     int* xvec = new int[sz];
 883     int* yvec = new int[sz];
 884     int oindex(0);
 885     int adjlabel(0);//adjacent label
 886     for( int j = 0; j < height; j++ )
 887     {
 888         for( int k = 0; k < width; k++ )
 889         {
 890             if( 0 > nlabels[oindex] )
 891             {
 892                 nlabels[oindex] = label;
 893                 //--------------------
 894                 // Start a new segment
 895                 //--------------------
 896                 xvec[0] = k;
 897                 yvec[0] = j;
 898                 //-------------------------------------------------------
 899                 // Quickly find an adjacent label for use later if needed
 900                 //-------------------------------------------------------
 901                 {for( int n = 0; n < 4; n++ )
 902                 {
 903                     int x = xvec[0] + dx4[n];
 904                     int y = yvec[0] + dy4[n];
 905                     if( (x >= 0 && x < width) && (y >= 0 && y < height) )
 906                     {
 907                         int nindex = y*width + x;
 908                         if(nlabels[nindex] >= 0) adjlabel = nlabels[nindex];
 909                     }
 910                 }}
 911 
 912                 int count(1);
 913                 for( int c = 0; c < count; c++ )
 914                 {
 915                     for( int n = 0; n < 4; n++ )
 916                     {
 917                         int x = xvec[c] + dx4[n];
 918                         int y = yvec[c] + dy4[n];
 919 
 920                         if( (x >= 0 && x < width) && (y >= 0 && y < height) )
 921                         {
 922                             int nindex = y*width + x;
 923 
 924                             if( 0 > nlabels[nindex] && labels[oindex] == labels[nindex] )
 925                             {
 926                                 xvec[count] = x;
 927                                 yvec[count] = y;
 928                                 nlabels[nindex] = label;
 929                                 count++;
 930                             }
 931                         }
 932 
 933                     }
 934                 }
 935                 //-------------------------------------------------------
 936                 // If segment size is less then a limit, assign an
 937                 // adjacent label found before, and decrement label count.
 938                 //-------------------------------------------------------
 939                 if(count <= SUPSZ >> 2)
 940                 {
 941                     for( int c = 0; c < count; c++ )
 942                     {
 943                         int ind = yvec[c]*width+xvec[c];
 944                         nlabels[ind] = adjlabel;
 945                     }
 946                     label--;
 947                 }
 948                 label++;
 949             }
 950             oindex++;
 951         }
 952     }
 953     numlabels = label;
 954 
 955     if(xvec) delete [] xvec;
 956     if(yvec) delete [] yvec;
 957 }
 958 
 959 
 960 //===========================================================================
 961 ///    RelabelStraySupervoxels
 962 //===========================================================================
 963 void SLIC::EnforceSupervoxelLabelConnectivity(
 964     int**&                        labels,//input - previous labels, output - new labels
 965     const int&                    width,
 966     const int&                    height,
 967     const int&                    depth,
 968     int&                        numlabels,
 969     const int&                    STEP)
 970 {
 971     const int dx10[10] = {-1,  0,  1,  0, -1,  1,  1, -1,  0, 0};
 972     const int dy10[10] = { 0, -1,  0,  1, -1, -1,  1,  1,  0, 0};
 973     const int dz10[10] = { 0,  0,  0,  0,  0,  0,  0,  0, -1, 1};
 974 
 975     int sz = width*height;
 976     const int SUPSZ = STEP*STEP*STEP;
 977 
 978     int adjlabel(0);//adjacent label
 979         int* xvec = new int[SUPSZ*10];//a large enough size
 980         int* yvec = new int[SUPSZ*10];//a large enough size
 981         int* zvec = new int[SUPSZ*10];//a large enough size
 982     //------------------
 983     // memory allocation
 984     //------------------
 985     int** nlabels = new int*[depth];
 986     {for( int d = 0; d < depth; d++ )
 987     {
 988         nlabels[d] = new int[sz];
 989         for( int i = 0; i < sz; i++ ) nlabels[d][i] = -1;
 990     }}
 991     //------------------
 992     // labeling
 993     //------------------
 994     int lab(0);
 995     {for( int d = 0; d < depth; d++ )
 996     {
 997         int i(0);
 998         for( int h = 0; h < height; h++ )
 999         {
1000             for( int w = 0; w < width; w++ )
1001             {
1002                 if(nlabels[d][i] < 0)
1003                 {
1004                     nlabels[d][i] = lab;
1005                     //-------------------------------------------------------
1006                     // Quickly find an adjacent label for use later if needed
1007                     //-------------------------------------------------------
1008                     {for( int n = 0; n < 10; n++ )
1009                     {
1010                         int x = w + dx10[n];
1011                         int y = h + dy10[n];
1012                         int z = d + dz10[n];
1013                         if( (x >= 0 && x < width) && (y >= 0 && y < height) && (z >= 0 && z < depth) )
1014                         {
1015                             int nindex = y*width + x;
1016                             if(nlabels[z][nindex] >= 0)
1017                             {
1018                                 adjlabel = nlabels[z][nindex];
1019                             }
1020                         }
1021                     }}
1022                     
1023                     xvec[0] = w; yvec[0] = h; zvec[0] = d;
1024                     int count(1);
1025                     for( int c = 0; c < count; c++ )
1026                     {
1027                         for( int n = 0; n < 10; n++ )
1028                         {
1029                             int x = xvec[c] + dx10[n];
1030                             int y = yvec[c] + dy10[n];
1031                             int z = zvec[c] + dz10[n];
1032 
1033                             if( (x >= 0 && x < width) && (y >= 0 && y < height) && (z >= 0 && z < depth))
1034                             {
1035                                 int nindex = y*width + x;
1036 
1037                                 if( 0 > nlabels[z][nindex] && labels[d][i] == labels[z][nindex] )
1038                                 {
1039                                     xvec[count] = x;
1040                                     yvec[count] = y;
1041                                     zvec[count] = z;
1042                                     nlabels[z][nindex] = lab;
1043                                     count++;
1044                                 }
1045                             }
1046 
1047                         }
1048                     }
1049                     //-------------------------------------------------------
1050                     // If segment size is less then a limit, assign an
1051                     // adjacent label found before, and decrement label count.
1052                     //-------------------------------------------------------
1053                     if(count <= (SUPSZ >> 2))//this threshold can be changed according to needs
1054                     {
1055                         for( int c = 0; c < count; c++ )
1056                         {
1057                             int ind = yvec[c]*width+xvec[c];
1058                             nlabels[zvec[c]][ind] = adjlabel;
1059                         }
1060                         lab--;
1061                     }
1062                     //--------------------------------------------------------
1063                     lab++;
1064                 }
1065                 i++;
1066             }
1067         }
1068     }}
1069     //------------------
1070     // mem de-allocation
1071     //------------------
1072     {for( int d = 0; d < depth; d++ )
1073     {
1074         for( int i = 0; i < sz; i++ ) labels[d][i] = nlabels[d][i];
1075     }}
1076     {for( int d = 0; d < depth; d++ )
1077     {
1078         delete [] nlabels[d];
1079     }}
1080     delete [] nlabels;
1081     //------------------
1082     if(xvec) delete [] xvec;
1083     if(yvec) delete [] yvec;
1084     if(zvec) delete [] zvec;
1085     //------------------
1086     numlabels = lab;
1087     //------------------
1088 }
1089 
1090 //===========================================================================
1091 ///    DoSuperpixelSegmentation_ForGivenSuperpixelSize
1092 ///
1093 /// The input parameter ubuff conains RGB values in a 32-bit unsigned integers
1094 /// as follows:
1095 ///
1096 /// [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]
1097 ///
1098 ///        Nothing              R                 G                  B
1099 ///
1100 /// The RGB values are accessed from (and packed into) the unsigned integers
1101 /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
1102 ///
1103 /// compactness value depends on the input pixels values. For instance, if
1104 /// the input is greyscale with values ranging from 0-100, then a compactness
1105 /// value of 20.0 would give good results. A greater value will make the
1106 /// superpixels more compact while a smaller value would make them more uneven.
1107 ///
1108 /// The labels can be saved if needed using SaveSuperpixelLabels()
1109 //===========================================================================
1110 void SLIC::DoSuperpixelSegmentation_ForGivenSuperpixelSize(
1111     const unsigned int*         ubuff,
1112     const int                    width,
1113     const int                    height,
1114     int*&                        klabels,
1115     int&                        numlabels,
1116     const int&                    superpixelsize,
1117     const double&               compactness)
1118 {
1119     //------------------------------------------------
1120     const int STEP = sqrt(double(superpixelsize))+0.5;
1121     //------------------------------------------------
1122     vector<double> kseedsl(0);
1123     vector<double> kseedsa(0);
1124     vector<double> kseedsb(0);
1125     vector<double> kseedsx(0);
1126     vector<double> kseedsy(0);
1127 
1128     //--------------------------------------------------
1129     m_width  = width;
1130     m_height = height;
1131     int sz = m_width*m_height;
1132     //klabels.resize( sz, -1 );
1133     //--------------------------------------------------
1134     klabels = new int[sz];
1135     for( int s = 0; s < sz; s++ ) klabels[s] = -1;
1136     //--------------------------------------------------
1137     if(1)//LAB, the default option
1138     {
1139         DoRGBtoLABConversion(ubuff, m_lvec, m_avec, m_bvec);
1140     }
1141     else//RGB
1142     {
1143         m_lvec = new double[sz]; m_avec = new double[sz]; m_bvec = new double[sz];
1144         for( int i = 0; i < sz; i++ )
1145         {
1146                 m_lvec[i] = ubuff[i] >> 16 & 0xff;
1147                 m_avec[i] = ubuff[i] >>  8 & 0xff;
1148                 m_bvec[i] = ubuff[i]       & 0xff;
1149         }
1150     }
1151     //--------------------------------------------------
1152     bool perturbseeds(false);//perturb seeds is not absolutely necessary, one can set this flag to false
1153     vector<double> edgemag(0);
1154     if(perturbseeds) DetectLabEdges(m_lvec, m_avec, m_bvec, m_width, m_height, edgemag);
1155     GetLABXYSeeds_ForGivenStepSize(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, STEP, perturbseeds, edgemag);
1156 
1157     PerformSuperpixelSLIC(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, klabels, STEP, edgemag,compactness);
1158     numlabels = kseedsl.size();
1159 
1160     int* nlabels = new int[sz];
1161     EnforceLabelConnectivity(klabels, m_width, m_height, nlabels, numlabels, double(sz)/double(STEP*STEP));
1162     {for(int i = 0; i < sz; i++ ) klabels[i] = nlabels[i];}
1163     if(nlabels) delete [] nlabels;
1164 }
1165 
1166 //===========================================================================
1167 ///    DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels
1168 ///
1169 /// The input parameter ubuff conains RGB values in a 32-bit unsigned integers
1170 /// as follows:
1171 ///
1172 /// [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]
1173 ///
1174 ///        Nothing              R                 G                  B
1175 ///
1176 /// The RGB values are accessed from (and packed into) the unsigned integers
1177 /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
1178 ///
1179 /// compactness value depends on the input pixels values. For instance, if
1180 /// the input is greyscale with values ranging from 0-100, then a compactness
1181 /// value of 20.0 would give good results. A greater value will make the
1182 /// superpixels more compact while a smaller value would make them more uneven.
1183 ///
1184 /// The labels can be saved if needed using SaveSuperpixelLabels()
1185 //===========================================================================
1186 void SLIC::DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(
1187     const unsigned int*                             ubuff,
1188     const int                    width,
1189     const int                    height,
1190     int*&                        klabels,
1191     int&                        numlabels,
1192     const int&                    K,//required number of superpixels
1193     const double&                                   compactness)//weight given to spatial distance
1194 {
1195     const int superpixelsize = 0.5+double(width*height)/double(K);
1196     DoSuperpixelSegmentation_ForGivenSuperpixelSize(ubuff,width,height,klabels,numlabels,superpixelsize,compactness);
1197 }
1198 
1199 //===========================================================================
1200 ///    DoSupervoxelSegmentation
1201 ///
1202 /// There is option to save the labels if needed.
1203 ///
1204 /// The input parameter ubuffvec holds all the video frames. It is a
1205 /// 2-dimensional array. The first dimension is depth and the second dimension
1206 /// is pixel location in a frame. For example, to access a pixel in the 3rd
1207 /// frame (i.e. depth index 2), in the 4th row (i.e. height index 3) on the
1208 /// 37th column (i.e. width index 36), you would write:
1209 ///
1210 /// unsigned int the_pixel_i_want = ubuffvec[2][3*width + 36]
1211 ///
1212 /// In addition, here is how the RGB values are contained in a 32-bit unsigned
1213 /// integer:
1214 ///
1215 /// [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]  [1 1 1 1 1 1 1 1]
1216 ///
1217 ///        Nothing              R                 G                  B
1218 ///
1219 /// The RGB values are accessed from (and packed into) the unsigned integers
1220 /// using bitwise operators as can be seen in the function DoRGBtoLABConversion().
1221 ///
1222 /// compactness value depends on the input pixels values. For instance, if
1223 /// the input is greyscale with values ranging from 0-100, then a compactness
1224 /// value of 20.0 would give good results. A greater value will make the
1225 /// supervoxels more compact while a smaller value would make them more uneven.
1226 //===========================================================================
1227 void SLIC::DoSupervoxelSegmentation(
1228     unsigned int**&                ubuffvec,
1229     const int&                    width,
1230     const int&                    height,
1231     const int&                    depth,
1232     int**&                        klabels,
1233     int&                        numlabels,
1234     const int&                    supervoxelsize,
1235     const double&               compactness)
1236 {
1237     //---------------------------------------------------------
1238     const int STEP = 0.5 + pow(double(supervoxelsize),1.0/3.0);
1239     //---------------------------------------------------------
1240     vector<double> kseedsl(0);
1241     vector<double> kseedsa(0);
1242     vector<double> kseedsb(0);
1243     vector<double> kseedsx(0);
1244     vector<double> kseedsy(0);
1245     vector<double> kseedsz(0);
1246 
1247     //--------------------------------------------------
1248     m_width  = width;
1249     m_height = height;
1250     m_depth  = depth;
1251     int sz = m_width*m_height;
1252     
1253     //--------------------------------------------------
1254         //klabels = new int*[depth];
1255     m_lvecvec = new double*[depth];
1256     m_avecvec = new double*[depth];
1257     m_bvecvec = new double*[depth];
1258     for( int d = 0; d < depth; d++ )
1259     {
1260                 //klabels[d] = new int[sz];
1261         m_lvecvec[d] = new double[sz];
1262         m_avecvec[d] = new double[sz];
1263         m_bvecvec[d] = new double[sz];
1264         for( int s = 0; s < sz; s++ )
1265         {
1266             klabels[d][s] = -1;
1267         }
1268     }
1269     
1270     DoRGBtoLABConversion(ubuffvec, m_lvecvec, m_avecvec, m_bvecvec);
1271 
1272     GetKValues_LABXYZ(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, kseedsz, STEP);
1273 
1274     PerformSupervoxelSLIC(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, kseedsz, klabels, STEP, compactness);
1275 
1276     EnforceSupervoxelLabelConnectivity(klabels, width, height, depth, numlabels, STEP);
1277 }

主程序main

  1 #if 1
  2 #include <iostream>  
  3 #include <time.h>
  4 #include "opencv2/opencv.hpp" 
  5 #include "SLIC.h"
  6 using namespace std;
  7 using namespace cv;
  8 int imgOpenCV2SLIC(Mat img, int &height, int &width, int &dim, unsigned int * &image);
  9 int imgSLIC2openCV(unsigned int *image, int height, int width, int dim, Mat &imgSLIC);
 10 int main()
 11 {
 12 
 13     Mat imgRGB;
 14     time_t tStart,tEnd,exeT;
 15 
 16     imgRGB= imread("C:\\Users\\Administrator\\Desktop\\file\\opencv\\stem_recognition\\ConsoleApplication1\\7.jpg");
 17     if (imgRGB.empty() == true){
 18         cout<<"can not open rgb image!"<<endl;
 19     }
 20 
 21     unsigned int *image; 
 22 
 23     int height; 
 24     int width; 
 25     int dim;
 26     long imgSize;
 27     
 28     int numlabels(0);
 29     SLIC slic;
 30     int m_spcount= 100 ;
 31     int m_compactness=10;
 32     imgOpenCV2SLIC(imgRGB,  height,  width,  dim, image);//OpenCV 图像数据转换成SLIC图像数据
 33     imgSize = height* width;
 34     int* labels = new int[imgSize];
 35 
 36     tStart=clock();
 37     //SLIC超像素分割,代码下载网站:http://ivrl.epfl.ch/research/superpixels#SLICO
 38     slic.DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(image, width, height, labels, numlabels, m_spcount, m_compactness);
 39     slic.DrawContoursAroundSegments(image, labels, width, height, 0);
 40 
 41     tEnd=clock();
 42     exeT=tEnd-tStart;
 43 
 44     Mat imgSLIC;
 45 
 46     imgSLIC2openCV(image, height,width,dim,imgSLIC);//SLIC结果:SLIC图像数据转换成OpenCV 图像数据
 47 
 48 
 49     //结果显示
 50     cout<<"SLIC执行时间exeT:"<<exeT<<"毫秒"<<endl;
 51     imshow("imgRGB",imgRGB);
 52     imshow("imgSLIC1",imgSLIC);
 53     waitKey();
 54     return 0;
 55 
 56 }
 57 
 58 
 59 //OpenCV Mat图像数据转换为SLIC图像数据
 60 //输入:Mat img, int &height, int &width, int &dim,
 61 //输出:unsigned int * &image,同时返回转换是否成功的标志:成功为0,识别为1
 62 int imgOpenCV2SLIC(Mat img, int &height, int &width, int &dim, unsigned int * &image)
 63 {
 64     int error=0;
 65     if( img.empty() ) //请一定检查是否成功读图 
 66     { 
 67         error =1;
 68     } 
 69 
 70     dim=img.channels();//图像通道数目
 71     height=img.rows;
 72     width=img.cols;
 73 
 74     int imgSize=width*height;
 75 
 76     unsigned char *pImage  = new unsigned char [imgSize*4];
 77     if(dim==1){
 78         for(int j = 0; j < height; j++){
 79             uchar * ptr = img.ptr<uchar>(j);
 80             for(int i = 0; i < width; i++) {
 81                 pImage[j * width*4 + 4*i+3] = 0;
 82                 pImage[j * width*4 + 4*i+2] = ptr[0];
 83                 pImage[j * width*4 + 4*i+1] = ptr[0];
 84                 pImage[j * width*4 + 4*i] = ptr[0];        
 85                 ptr ++;
 86             }
 87         }
 88     }
 89     else{
 90         if(dim==3){
 91             for(int j = 0; j < height; j++){
 92                 Vec3b * ptr = img.ptr<Vec3b>(j);
 93                 for(int i = 0; i < width; i++) {
 94                     pImage[j * width*4 + 4*i+3] = 0;
 95                     pImage[j * width*4 + 4*i+2] = ptr[0][2];//R
 96                     pImage[j * width*4 + 4*i+1] = ptr[0][1];//G
 97                     pImage[j * width*4 + 4*i]   = ptr[0][0];//B        
 98                     ptr ++;
 99                 }
100             }
101         }
102         else  error=1;
103 
104     }
105 
106     image = new unsigned int[imgSize];
107     memcpy( image, (unsigned int*)pImage, imgSize*sizeof(unsigned int) );
108     delete pImage;
109 
110     return error;
111 
112 }
113 
114 
115 //SLIC图像数据转换为OpenCV Mat图像数据
116 //输入:unsigned int *image, int height, int width, int dim
117 //输出:Mat &imgSLIC ,同时返回转换是否成功的标志:成功为0,识别为1
118 int imgSLIC2openCV(unsigned int *image, int height, int width, int dim, Mat &imgSLIC)
119 {
120     int error=0;//转换是否成功的标志:成功为0,识别为1
121 
122     if(dim==1){
123         imgSLIC.create(height, width, CV_8UC1);
124         //遍历所有像素,并设置像素值 
125         for( int j = 0; j< height; ++j) 
126         { 
127             //获取第 i行首像素指针 
128             uchar * p = imgSLIC.ptr<uchar>(j); 
129             //对第 i行的每个像素(byte)操作 
130             for( int i = 0; i < width; ++i ) 
131                 p[i] =(unsigned char)(image[j*width+i]& 0xFF)  ; 
132         } 
133     }
134     else{
135         if(dim==3){
136             imgSLIC.create(height, width, CV_8UC3);
137             //遍历所有像素,并设置像素值 
138             for( int j = 0; j < height; ++j) 
139             { 
140                 //获取第 i行首像素指针 
141                 Vec3b * p = imgSLIC.ptr<Vec3b>(j); 
142                 for( int i = 0; i < width; ++i ) 
143                 { 
144                     p[i][0] = (unsigned char)(image[j*width+i]          & 0xFF ); //Blue 
145                     p[i][1] = (unsigned char)((image[j*width+i] >>  8 ) & 0xFF ); //Green 
146                     p[i][2] = (unsigned char)((image[j*width+i] >>  16) & 0xFF ) ; //Red 
147                 } 
148             }
149         }
150         else  error= 1 ;
151 
152     }
153 
154     return error;
155 }
156 
157 
158 
159 #endif