• 超像素分割


    头文件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
  • 相关阅读:
    新概念4-38
    新概念4-37
    新概念4-36
    新概念4-35
    国史通鉴-03 天下为私 04
    新概念4-34
    西门子 框架断路器 及其他中低压配电设备资料查询
    OPC UA 的本质
    经典Scout添加等时同步设备
    同步报故障解同步启动
  • 原文地址:https://www.cnblogs.com/hsy1941/p/9212951.html
Copyright © 2020-2023  润新知