LCOV - code coverage report
Current view: top level - root/study/test02/IPCC - SLIC.cpp (source / functions) Hit Total Coverage
Test: SLIC.info Lines: 355 365 97.3 %
Date: 2022-05-07 20:52:35 Functions: 17 18 94.4 %

          Line data    Source code
       1             : // SLIC.cpp: implementation of the SLIC class.
       2             : //===========================================================================
       3             : // This code implements the zero parameter superpixel segmentation technique
       4             : // described in:
       5             : //
       6             : //
       7             : //
       8             : // "SLIC Superpixels Compared to State-of-the-art Superpixel Methods"
       9             : //
      10             : // Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua,
      11             : // and Sabine Susstrunk,
      12             : //
      13             : // IEEE TPAMI, Volume 34, Issue 11, Pages 2274-2282, November 2012.
      14             : //
      15             : // https://www.epfl.ch/labs/ivrl/research/slic-superpixels/
      16             : //===========================================================================
      17             : // Copyright (c) 2013 Radhakrishna Achanta.
      18             : //
      19             : // For commercial use please contact the author:
      20             : //
      21             : // Email: firstname.lastname@epfl.ch
      22             : //===========================================================================
      23             : 
      24             : #include <stdio.h>
      25             : #include <cfloat>
      26             : #include <cmath>
      27             : #include <iostream>
      28             : #include <fstream>
      29             : #include "SLIC.h"
      30             : #include <chrono>
      31             : 
      32             : typedef chrono::high_resolution_clock Clock;
      33             : 
      34             : // For superpixels
      35             : const int dx4[4] = {-1,  0,  1,  0};
      36             : const int dy4[4] = { 0, -1,  0,  1};
      37             : //const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
      38             : //const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
      39             : 
      40             : // For supervoxels
      41             : const int dx10[10] = {-1,  0,  1,  0, -1,  1,  1, -1,  0, 0};
      42             : const int dy10[10] = { 0, -1,  0,  1, -1, -1,  1,  1,  0, 0};
      43             : const int dz10[10] = { 0,  0,  0,  0,  0,  0,  0,  0, -1, 1};
      44             : 
      45             : //////////////////////////////////////////////////////////////////////
      46             : // Construction/Destruction
      47             : //////////////////////////////////////////////////////////////////////
      48             : 
      49           1 : SLIC::SLIC()
      50             : {
      51           1 :         m_lvec = NULL;
      52           1 :         m_avec = NULL;
      53           1 :         m_bvec = NULL;
      54             : 
      55           1 :         m_lvecvec = NULL;
      56           1 :         m_avecvec = NULL;
      57           1 :         m_bvecvec = NULL;
      58           1 : }
      59             : 
      60           1 : SLIC::~SLIC()
      61             : {
      62           1 :         if(m_lvec) delete [] m_lvec;
      63           1 :         if(m_avec) delete [] m_avec;
      64           1 :         if(m_bvec) delete [] m_bvec;
      65             : 
      66             : 
      67           1 :         if(m_lvecvec)
      68             :         {
      69           0 :                 for( int d = 0; d < m_depth; d++ ) delete [] m_lvecvec[d];
      70           0 :                 delete [] m_lvecvec;
      71             :         }
      72           1 :         if(m_avecvec)
      73             :         {
      74           0 :                 for( int d = 0; d < m_depth; d++ ) delete [] m_avecvec[d];
      75           0 :                 delete [] m_avecvec;
      76             :         }
      77           1 :         if(m_bvecvec)
      78             :         {
      79           0 :                 for( int d = 0; d < m_depth; d++ ) delete [] m_bvecvec[d];
      80           0 :                 delete [] m_bvecvec;
      81             :         }
      82           1 : }
      83             : 
      84             : //==============================================================================
      85             : ///     RGB2XYZ
      86             : ///
      87             : /// sRGB (D65 illuninant assumption) to XYZ conversion
      88             : //==============================================================================
      89    10130902 : void SLIC::RGB2XYZ(
      90             :         const int&          sR,
      91             :         const int&          sG,
      92             :         const int&          sB,
      93             :         double&                     X,
      94             :         double&                     Y,
      95             :         double&                     Z)
      96             : {
      97    10130902 :         double R = sR/255.0;
      98    10130902 :         double G = sG/255.0;
      99    10130902 :         double B = sB/255.0;
     100             : 
     101             :         double r, g, b;
     102             : 
     103    10130902 :         if(R <= 0.04045)     r = R/12.92;
     104     9593232 :         else                            r = pow((R+0.055)/1.055,2.4);
     105    10130902 :         if(G <= 0.04045)     g = G/12.92;
     106     9896286 :         else                            g = pow((G+0.055)/1.055,2.4);
     107    10130902 :         if(B <= 0.04045)     b = B/12.92;
     108     9712489 :         else                            b = pow((B+0.055)/1.055,2.4);
     109             : 
     110    10130902 :         X = r*0.4124564 + g*0.3575761 + b*0.1804375;
     111    10130902 :         Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
     112    10130902 :         Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
     113    10130902 : }
     114             : 
     115             : //===========================================================================
     116             : ///     RGB2LAB
     117             : //===========================================================================
     118    10130902 : void SLIC::RGB2LAB(const int& sR, const int& sG, const int& sB, double& lval, double& aval, double& bval)
     119             : {
     120             :         //------------------------
     121             :         // sRGB to XYZ conversion
     122             :         //------------------------
     123             :         double X, Y, Z;
     124    10130902 :         RGB2XYZ(sR, sG, sB, X, Y, Z);
     125             : 
     126             :         //------------------------
     127             :         // XYZ to LAB conversion
     128             :         //------------------------
     129    10130902 :         double epsilon = 0.008856;      //actual CIE standard
     130    10130902 :         double kappa   = 903.3;         //actual CIE standard
     131             : 
     132    10130902 :         double Xr = 0.950456;   //reference white
     133    10130902 :         double Yr = 1.0;                //reference white
     134    10130902 :         double Zr = 1.088754;   //reference white
     135             : 
     136    10130902 :         double xr = X/Xr;
     137    10130902 :         double yr = Y/Yr;
     138    10130902 :         double zr = Z/Zr;
     139             : 
     140             :         double fx, fy, fz;
     141    10130902 :         if(xr > epsilon)     fx = pow(xr, 1.0/3.0);
     142      669542 :         else                            fx = (kappa*xr + 16.0)/116.0;
     143    10130902 :         if(yr > epsilon)     fy = pow(yr, 1.0/3.0);
     144      512690 :         else                            fy = (kappa*yr + 16.0)/116.0;
     145    10130902 :         if(zr > epsilon)     fz = pow(zr, 1.0/3.0);
     146      766636 :         else                            fz = (kappa*zr + 16.0)/116.0;
     147             : 
     148    10130902 :         lval = 116.0*fy-16.0;
     149    10130902 :         aval = 500.0*(fx-fy);
     150    10130902 :         bval = 200.0*(fy-fz);
     151    10130902 : }
     152             : 
     153             : //===========================================================================
     154             : ///     DoRGBtoLABConversion
     155             : ///
     156             : ///     For whole image: overlaoded floating point version
     157             : //===========================================================================
     158           1 : void SLIC::DoRGBtoLABConversion(
     159             :         const unsigned int*&                ubuff,
     160             :         double*&                                    lvec,
     161             :         double*&                                    avec,
     162             :         double*&                                    bvec)
     163             : {
     164           1 :         int sz = m_width*m_height;
     165           1 :         lvec = new double[sz];
     166           1 :         avec = new double[sz];
     167           1 :         bvec = new double[sz];
     168             : 
     169    10130903 :         for( int j = 0; j < sz; j++ )
     170             :         {
     171    10130902 :                 int r = (ubuff[j] >> 16) & 0xFF;
     172    10130902 :                 int g = (ubuff[j] >>  8) & 0xFF;
     173    10130902 :                 int b = (ubuff[j]      ) & 0xFF;
     174             : 
     175    10130902 :                 RGB2LAB( r, g, b, lvec[j], avec[j], bvec[j] );
     176             :         }
     177           1 : }
     178             : 
     179             : //==============================================================================
     180             : ///     DetectLabEdges
     181             : //==============================================================================
     182           1 : void SLIC::DetectLabEdges(
     183             :         const double*                           lvec,
     184             :         const double*                           avec,
     185             :         const double*                           bvec,
     186             :         const int&                                  width,
     187             :         const int&                                  height,
     188             :         vector<double>&                               edges)
     189             : {
     190           1 :         int sz = width*height;
     191             : 
     192           1 :         edges.resize(sz,0);
     193        3897 :         for( int j = 1; j < height-1; j++ )
     194             :         {
     195    10121808 :                 for( int k = 1; k < width-1; k++ )
     196             :                 {
     197    10117912 :                         int i = j*width+k;
     198             : 
     199    20235824 :                         double dx = (lvec[i-1]-lvec[i+1])*(lvec[i-1]-lvec[i+1]) +
     200    10117912 :                                                 (avec[i-1]-avec[i+1])*(avec[i-1]-avec[i+1]) +
     201    10117912 :                                                 (bvec[i-1]-bvec[i+1])*(bvec[i-1]-bvec[i+1]);
     202             : 
     203    20235824 :                         double dy = (lvec[i-width]-lvec[i+width])*(lvec[i-width]-lvec[i+width]) +
     204    10117912 :                                                 (avec[i-width]-avec[i+width])*(avec[i-width]-avec[i+width]) +
     205    10117912 :                                                 (bvec[i-width]-bvec[i+width])*(bvec[i-width]-bvec[i+width]);
     206             : 
     207             :                         //edges[i] = (sqrt(dx) + sqrt(dy));
     208    10117912 :                         edges[i] = (dx + dy);
     209             :                 }
     210             :         }
     211           1 : }
     212             : 
     213             : //===========================================================================
     214             : ///     PerturbSeeds
     215             : //===========================================================================
     216           1 : void SLIC::PerturbSeeds(
     217             :         vector<double>&                               kseedsl,
     218             :         vector<double>&                               kseedsa,
     219             :         vector<double>&                               kseedsb,
     220             :         vector<double>&                               kseedsx,
     221             :         vector<double>&                               kseedsy,
     222             :         const vector<double>&         edges)
     223             : {
     224           1 :         const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
     225           1 :         const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
     226             :         
     227           1 :         int numseeds = kseedsl.size();
     228             : 
     229         197 :         for( int n = 0; n < numseeds; n++ )
     230             :         {
     231         196 :                 int ox = kseedsx[n];//original x
     232         196 :                 int oy = kseedsy[n];//original y
     233         196 :                 int oind = oy*m_width + ox;
     234             : 
     235         196 :                 int storeind = oind;
     236        1764 :                 for( int i = 0; i < 8; i++ )
     237             :                 {
     238        1568 :                         int nx = ox+dx8[i];//new x
     239        1568 :                         int ny = oy+dy8[i];//new y
     240             : 
     241        1568 :                         if( nx >= 0 && nx < m_width && ny >= 0 && ny < m_height)
     242             :                         {
     243        1568 :                                 int nind = ny*m_width + nx;
     244        1568 :                                 if( edges[nind] < edges[storeind])
     245             :                                 {
     246         259 :                                         storeind = nind;
     247             :                                 }
     248             :                         }
     249             :                 }
     250         196 :                 if(storeind != oind)
     251             :                 {
     252         138 :                         kseedsx[n] = storeind%m_width;
     253         138 :                         kseedsy[n] = storeind/m_width;
     254         138 :                         kseedsl[n] = m_lvec[storeind];
     255         138 :                         kseedsa[n] = m_avec[storeind];
     256         138 :                         kseedsb[n] = m_bvec[storeind];
     257             :                 }
     258             :         }
     259           1 : }
     260             : 
     261             : //===========================================================================
     262             : ///     GetLABXYSeeds_ForGivenK
     263             : ///
     264             : /// The k seed values are taken as uniform spatial pixel samples.
     265             : //===========================================================================
     266           1 : void SLIC::GetLABXYSeeds_ForGivenK(
     267             :         vector<double>&                               kseedsl,
     268             :         vector<double>&                               kseedsa,
     269             :         vector<double>&                               kseedsb,
     270             :         vector<double>&                               kseedsx,
     271             :         vector<double>&                               kseedsy,
     272             :         const int&                                  K,
     273             :         const bool&                                 perturbseeds,
     274             :         const vector<double>&         edgemag)
     275             : {
     276           1 :         int sz = m_width*m_height;
     277           1 :         double step = sqrt(double(sz)/double(K));
     278           1 :         int T = step;
     279           1 :         int xoff = step/2;
     280           1 :         int yoff = step/2;
     281             :         
     282           1 :         int n(0);int r(0);
     283          18 :         for( int y = 0; y < m_height; y++ )
     284             :         {
     285          18 :                 int Y = y*step + yoff;
     286          18 :                 if( Y > m_height-1 ) break;
     287             : 
     288         213 :                 for( int x = 0; x < m_width; x++ )
     289             :                 {
     290             :                         //int X = x*step + xoff;//square grid
     291         213 :                         int X = x*step + (xoff<<(r&0x1));//hex grid
     292         213 :                         if(X > m_width-1) break;
     293             : 
     294         196 :                         int i = Y*m_width + X;
     295             : 
     296             :                         //_ASSERT(n < K);
     297             :                         
     298             :                         //kseedsl[n] = m_lvec[i];
     299             :                         //kseedsa[n] = m_avec[i];
     300             :                         //kseedsb[n] = m_bvec[i];
     301             :                         //kseedsx[n] = X;
     302             :                         //kseedsy[n] = Y;
     303         196 :                         kseedsl.push_back(m_lvec[i]);
     304         196 :                         kseedsa.push_back(m_avec[i]);
     305         196 :                         kseedsb.push_back(m_bvec[i]);
     306         196 :                         kseedsx.push_back(X);
     307         196 :                         kseedsy.push_back(Y);
     308         196 :                         n++;
     309             :                 }
     310          17 :                 r++;
     311             :         }
     312             : 
     313           1 :         if(perturbseeds)
     314             :         {
     315           1 :                 PerturbSeeds(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, edgemag);
     316             :         }
     317           1 : }
     318             : 
     319             : //===========================================================================
     320             : ///     PerformSuperpixelSegmentation_VariableSandM
     321             : ///
     322             : ///     Magic SLIC - no parameters
     323             : ///
     324             : ///     Performs k mean segmentation. It is fast because it looks locally, not
     325             : /// over the entire image.
     326             : /// This function picks the maximum value of color distance as compact factor
     327             : /// M and maximum pixel distance as grid step size S from each cluster (13 April 2011).
     328             : /// So no need to input a constant value of M and S. There are two clear
     329             : /// advantages:
     330             : ///
     331             : /// [1] The algorithm now better handles both textured and non-textured regions
     332             : /// [2] There is not need to set any parameters!!!
     333             : ///
     334             : /// SLICO (or SLIC Zero) dynamically varies only the compactness factor S,
     335             : /// not the step size S.
     336             : //===========================================================================
     337           1 : void SLIC::PerformSuperpixelSegmentation_VariableSandM(
     338             :         vector<double>&                               kseedsl,
     339             :         vector<double>&                               kseedsa,
     340             :         vector<double>&                               kseedsb,
     341             :         vector<double>&                               kseedsx,
     342             :         vector<double>&                               kseedsy,
     343             :         int*                                            klabels,
     344             :         const int&                                  STEP,
     345             :         const int&                                  NUMITR)
     346             : {
     347           1 :         int sz = m_width*m_height;
     348           1 :         const int numk = kseedsl.size();
     349             :         //double cumerr(99999.9);
     350           1 :         int numitr(0);
     351             : 
     352             :         //----------------
     353           1 :         int offset = STEP;
     354           1 :         if(STEP < 10) offset = STEP*1.5;
     355             :         //----------------
     356             : 
     357           1 :         vector<double> sigmal(numk, 0);
     358           2 :         vector<double> sigmaa(numk, 0);
     359           2 :         vector<double> sigmab(numk, 0);
     360           2 :         vector<double> sigmax(numk, 0);
     361           2 :         vector<double> sigmay(numk, 0);
     362           2 :         vector<int> clustersize(numk, 0);
     363           2 :         vector<double> inv(numk, 0);//to store 1/clustersize[k] values
     364           2 :         vector<double> distxy(sz, DBL_MAX);
     365           2 :         vector<double> distlab(sz, DBL_MAX);
     366           2 :         vector<double> distvec(sz, DBL_MAX);
     367           2 :         vector<double> maxlab(numk, 10*10);//THIS IS THE VARIABLE VALUE OF M, just start with 10
     368           2 :         vector<double> maxxy(numk, STEP*STEP);//THIS IS THE VARIABLE VALUE OF M, just start with 10
     369             : 
     370           1 :         double invxywt = 1.0/(STEP*STEP);//NOTE: this is different from how usual SLIC/LKM works
     371             : 
     372          12 :         while( numitr < NUMITR )
     373             :         {
     374             :                 //------
     375             :                 //cumerr = 0;
     376          10 :                 numitr++;
     377             :                 //------
     378             : 
     379          10 :                 distvec.assign(sz, DBL_MAX);
     380        1970 :                 for( int n = 0; n < numk; n++ )
     381             :                 {
     382        1960 :                         int y1 = max(0,                 (int)(kseedsy[n]-offset));
     383        1960 :                         int y2 = min(m_height,  (int)(kseedsy[n]+offset));
     384        1960 :                         int x1 = max(0,                 (int)(kseedsx[n]-offset));
     385        1960 :                         int x2 = min(m_width,   (int)(kseedsx[n]+offset));
     386             : 
     387      867855 :                         for( int y = y1; y < y2; y++ )
     388             :                         {
     389   377486194 :                                 for( int x = x1; x < x2; x++ )
     390             :                                 {
     391   376620299 :                                         int i = y*m_width + x;
     392             :                                         //_ASSERT( y < m_height && x < m_width && y >= 0 && x >= 0 );
     393             : 
     394   376620299 :                                         double l = m_lvec[i];
     395   376620299 :                                         double a = m_avec[i];
     396   376620299 :                                         double b = m_bvec[i];
     397             : 
     398   753240598 :                                         distlab[i] =    (l - kseedsl[n])*(l - kseedsl[n]) +
     399   753240598 :                                                                         (a - kseedsa[n])*(a - kseedsa[n]) +
     400   753240598 :                                                                         (b - kseedsb[n])*(b - kseedsb[n]);
     401             : 
     402   753240598 :                                         distxy[i] =             (x - kseedsx[n])*(x - kseedsx[n]) +
     403   753240598 :                                                                         (y - kseedsy[n])*(y - kseedsy[n]);
     404             : 
     405             :                                         //------------------------------------------------------------------------
     406   376620299 :                                         double dist = distlab[i]/maxlab[n] + distxy[i]*invxywt;//only varying m, prettier superpixels
     407             :                                         //double dist = distlab[i]/maxlab[n] + distxy[i]/maxxy[n];//varying both m and S
     408             :                                         //------------------------------------------------------------------------
     409             :                                         
     410   376620299 :                                         if( dist < distvec[i] )
     411             :                                         {
     412   206398438 :                                                 distvec[i] = dist;
     413   206398438 :                                                 klabels[i]  = n;
     414             :                                         }
     415             :                                 }
     416             :                         }
     417             :                 }
     418             :                 //-----------------------------------------------------------------
     419             :                 // Assign the max color distance for a cluster
     420             :                 //-----------------------------------------------------------------
     421          10 :                 if(0 == numitr)
     422             :                 {
     423           0 :                         maxlab.assign(numk,1);
     424           0 :                         maxxy.assign(numk,1);
     425             :                 }
     426   101309030 :                 {for( int i = 0; i < sz; i++ )
     427             :                 {
     428   101309020 :                         if(maxlab[klabels[i]] < distlab[i]) maxlab[klabels[i]] = distlab[i];
     429   101309020 :                         if(maxxy[klabels[i]] < distxy[i]) maxxy[klabels[i]] = distxy[i];
     430             :                 }}
     431             :                 //-----------------------------------------------------------------
     432             :                 // Recalculate the centroid and store in the seed values
     433             :                 //-----------------------------------------------------------------
     434          10 :                 sigmal.assign(numk, 0);
     435          10 :                 sigmaa.assign(numk, 0);
     436          10 :                 sigmab.assign(numk, 0);
     437          10 :                 sigmax.assign(numk, 0);
     438          10 :                 sigmay.assign(numk, 0);
     439          10 :                 clustersize.assign(numk, 0);
     440             : 
     441   101309030 :                 for( int j = 0; j < sz; j++ )
     442             :                 {
     443   101309020 :                         int temp = klabels[j];
     444             :                         //_ASSERT(klabels[j] >= 0);
     445   101309020 :                         sigmal[klabels[j]] += m_lvec[j];
     446   101309020 :                         sigmaa[klabels[j]] += m_avec[j];
     447   101309020 :                         sigmab[klabels[j]] += m_bvec[j];
     448   101309020 :                         sigmax[klabels[j]] += (j%m_width);
     449   101309020 :                         sigmay[klabels[j]] += (j/m_width);
     450             : 
     451   101309020 :                         clustersize[klabels[j]]++;
     452             :                 }
     453             : 
     454        1970 :                 {for( int k = 0; k < numk; k++ )
     455             :                 {
     456             :                         //_ASSERT(clustersize[k] > 0);
     457        1960 :                         if( clustersize[k] <= 0 ) clustersize[k] = 1;
     458        1960 :                         inv[k] = 1.0/double(clustersize[k]);//computing inverse now to multiply, than divide later
     459             :                 }}
     460             :                 
     461        1970 :                 {for( int k = 0; k < numk; k++ )
     462             :                 {
     463        1960 :                         kseedsl[k] = sigmal[k]*inv[k];
     464        1960 :                         kseedsa[k] = sigmaa[k]*inv[k];
     465        1960 :                         kseedsb[k] = sigmab[k]*inv[k];
     466        1960 :                         kseedsx[k] = sigmax[k]*inv[k];
     467        1960 :                         kseedsy[k] = sigmay[k]*inv[k];
     468             :                 }}
     469           1 :         }
     470           1 : }
     471             : 
     472             : //===========================================================================
     473             : ///     SaveSuperpixelLabels2PGM
     474             : ///
     475             : ///     Save labels to PGM in raster scan order.
     476             : //===========================================================================
     477           1 : void SLIC::SaveSuperpixelLabels2PPM(
     478             :         char*                           filename, 
     479             :         int *                           labels, 
     480             :         const int                       width, 
     481             :         const int                       height)
     482             : {
     483             :     FILE* fp;
     484             :     char header[20];
     485             :  
     486           1 :     fp = fopen(filename, "wb");
     487             :  
     488             :     // write the PPM header info, such as type, width, height and maximum
     489           1 :     fprintf(fp,"P6\n%d %d\n255\n", width, height);
     490             :  
     491             :     // write the RGB data
     492           1 :     unsigned char *rgb = new unsigned char [ (width)*(height)*3 ];
     493           1 :     int k = 0;
     494           1 :         unsigned char c = 0;
     495        3899 :     for ( int i = 0; i < (height); i++ ) {
     496    10134800 :         for ( int j = 0; j < (width); j++ ) {
     497    10130902 :                         c = (unsigned char)(labels[k]);
     498    10130902 :             rgb[i*(width)*3 + j*3 + 2] = labels[k] >> 16 & 0xff;  // r
     499    10130902 :             rgb[i*(width)*3 + j*3 + 1] = labels[k] >> 8  & 0xff;  // g
     500    10130902 :             rgb[i*(width)*3 + j*3 + 0] = labels[k]       & 0xff;  // b
     501             : 
     502             :                         // rgb[i*(width) + j + 0] = c;
     503    10130902 :             k++;
     504             :         }
     505             :     }
     506           1 :     fwrite(rgb, width*height*3, 1, fp);
     507             : 
     508           1 :     delete [] rgb;
     509             :  
     510           1 :     fclose(fp);
     511             : 
     512           1 : }
     513             : 
     514             : //===========================================================================
     515             : ///     EnforceLabelConnectivity
     516             : ///
     517             : ///             1. finding an adjacent label for each new component at the start
     518             : ///             2. if a certain component is too small, assigning the previously found
     519             : ///                 adjacent label to this component, and not incrementing the label.
     520             : //===========================================================================
     521           1 : void SLIC::EnforceLabelConnectivity(
     522             :         const int*                                      labels,//input labels that need to be corrected to remove stray labels
     523             :         const int&                                  width,
     524             :         const int&                                  height,
     525             :         int*                                            nlabels,//new labels
     526             :         int&                                                numlabels,//the number of labels changes in the end if segments are removed
     527             :         const int&                                  K) //the number of superpixels desired by the user
     528             : {
     529             : //      const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
     530             : //      const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
     531             : 
     532           1 :         const int dx4[4] = {-1,  0,  1,  0};
     533           1 :         const int dy4[4] = { 0, -1,  0,  1};
     534             : 
     535           1 :         const int sz = width*height;
     536           1 :         const int SUPSZ = sz/K;
     537             :         //nlabels.resize(sz, -1);
     538           1 :         for( int i = 0; i < sz; i++ ) nlabels[i] = -1;
     539           1 :         int label(0);
     540           1 :         int* xvec = new int[sz];
     541           1 :         int* yvec = new int[sz];
     542           1 :         int oindex(0);
     543           1 :         int adjlabel(0);//adjacent label
     544        3899 :         for( int j = 0; j < height; j++ )
     545             :         {
     546    10134800 :                 for( int k = 0; k < width; k++ )
     547             :                 {
     548    10130902 :                         if( 0 > nlabels[oindex] )
     549             :                         {
     550         579 :                                 nlabels[oindex] = label;
     551             :                                 //--------------------
     552             :                                 // Start a new segment
     553             :                                 //--------------------
     554         579 :                                 xvec[0] = k;
     555         579 :                                 yvec[0] = j;
     556             :                                 //-------------------------------------------------------
     557             :                                 // Quickly find an adjacent label for use later if needed
     558             :                                 //-------------------------------------------------------
     559        2895 :                                 {for( int n = 0; n < 4; n++ )
     560             :                                 {
     561        2316 :                                         int x = xvec[0] + dx4[n];
     562        2316 :                                         int y = yvec[0] + dy4[n];
     563        2316 :                                         if( (x >= 0 && x < width) && (y >= 0 && y < height) )
     564             :                                         {
     565        2296 :                                                 int nindex = y*width + x;
     566        2296 :                                                 if(nlabels[nindex] >= 0) adjlabel = nlabels[nindex];
     567             :                                         }
     568             :                                 }}
     569             : 
     570         579 :                                 int count(1);
     571    10131481 :                                 for( int c = 0; c < count; c++ )
     572             :                                 {
     573    50654510 :                                         for( int n = 0; n < 4; n++ )
     574             :                                         {
     575    40523608 :                                                 int x = xvec[c] + dx4[n];
     576    40523608 :                                                 int y = yvec[c] + dy4[n];
     577             : 
     578    40523608 :                                                 if( (x >= 0 && x < width) && (y >= 0 && y < height) )
     579             :                                                 {
     580    40510614 :                                                         int nindex = y*width + x;
     581             : 
     582    40510614 :                                                         if( 0 > nlabels[nindex] && labels[oindex] == labels[nindex] )
     583             :                                                         {
     584    10130323 :                                                                 xvec[count] = x;
     585    10130323 :                                                                 yvec[count] = y;
     586    10130323 :                                                                 nlabels[nindex] = label;
     587    10130323 :                                                                 count++;
     588             :                                                         }
     589             :                                                 }
     590             : 
     591             :                                         }
     592             :                                 }
     593             :                                 //-------------------------------------------------------
     594             :                                 // If segment size is less then a limit, assign an
     595             :                                 // adjacent label found before, and decrement label count.
     596             :                                 //-------------------------------------------------------
     597         579 :                                 if(count <= SUPSZ >> 2)
     598             :                                 {
     599       47277 :                                         for( int c = 0; c < count; c++ )
     600             :                                         {
     601       46894 :                                                 int ind = yvec[c]*width+xvec[c];
     602       46894 :                                                 nlabels[ind] = adjlabel;
     603             :                                         }
     604         383 :                                         label--;
     605             :                                 }
     606         579 :                                 label++;
     607             :                         }
     608    10130902 :                         oindex++;
     609             :                 }
     610             :         }
     611           1 :         numlabels = label;
     612             : 
     613           1 :         if(xvec) delete [] xvec;
     614           1 :         if(yvec) delete [] yvec;
     615           1 : }
     616             : 
     617             : //===========================================================================
     618             : ///     PerformSLICO_ForGivenK
     619             : ///
     620             : /// Zero parameter SLIC algorithm for a given number K of superpixels.
     621             : //===========================================================================
     622           1 : void SLIC::PerformSLICO_ForGivenK(
     623             :         const unsigned int*                     ubuff,
     624             :         const int                                       width,
     625             :         const int                                       height,
     626             :         int*                                            klabels,
     627             :         int&                                                numlabels,
     628             :         const int&                                  K,//required number of superpixels
     629             :         const double&                               m)//weight given to spatial distance
     630             : {
     631           1 :         vector<double> kseedsl(0);
     632           2 :         vector<double> kseedsa(0);
     633           2 :         vector<double> kseedsb(0);
     634           2 :         vector<double> kseedsx(0);
     635           2 :         vector<double> kseedsy(0);
     636             : 
     637             :         //--------------------------------------------------
     638           1 :         m_width  = width;
     639           1 :         m_height = height;
     640           1 :         int sz = m_width*m_height;
     641             :         //--------------------------------------------------
     642             :         //if(0 == klabels) klabels = new int[sz];
     643           1 :         for( int s = 0; s < sz; s++ ) klabels[s] = -1;
     644             :         //--------------------------------------------------
     645             :         if(1)//LAB
     646             :         {
     647           1 :                 DoRGBtoLABConversion(ubuff, m_lvec, m_avec, m_bvec);
     648             :         }
     649             :         else//RGB
     650             :         {
     651             :                 m_lvec = new double[sz]; m_avec = new double[sz]; m_bvec = new double[sz];
     652             :                 for( int i = 0; i < sz; i++ )
     653             :                 {
     654             :                         m_lvec[i] = ubuff[i] >> 16 & 0xff;
     655             :                         m_avec[i] = ubuff[i] >>  8 & 0xff;
     656             :                         m_bvec[i] = ubuff[i]       & 0xff;
     657             :                 }
     658             :         }
     659             :         //--------------------------------------------------
     660             : 
     661           1 :         bool perturbseeds(true);
     662           2 :         vector<double> edgemag(0);
     663           1 :         if(perturbseeds) DetectLabEdges(m_lvec, m_avec, m_bvec, m_width, m_height, edgemag);
     664           1 :         GetLABXYSeeds_ForGivenK(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, K, perturbseeds, edgemag);
     665             : 
     666           1 :         int STEP = sqrt(double(sz)/double(K)) + 2.0;//adding a small value in the even the STEP size is too small.
     667           1 :         PerformSuperpixelSegmentation_VariableSandM(kseedsl,kseedsa,kseedsb,kseedsx,kseedsy,klabels,STEP,10);
     668           1 :         numlabels = kseedsl.size();
     669             : 
     670           1 :         int* nlabels = new int[sz];
     671           1 :         EnforceLabelConnectivity(klabels, m_width, m_height, nlabels, numlabels, K);
     672           1 :         {for(int i = 0; i < sz; i++ ) klabels[i] = nlabels[i];}
     673           2 :         if(nlabels) delete [] nlabels;
     674           1 : }
     675             : 
     676             : //===========================================================================
     677             : /// Load PPM file
     678             : ///
     679             : /// 
     680             : //===========================================================================
     681           1 : void LoadPPM(char* filename, unsigned int** data, int* width, int* height)
     682             : {
     683             :     char header[1024];
     684           1 :     FILE* fp = NULL;
     685           1 :     int line = 0;
     686             :  
     687           1 :     fp = fopen(filename, "rb");
     688             :  
     689             :     // read the image type, such as: P6
     690             :     // skip the comment lines
     691           4 :     while (line < 2) {    
     692           2 :         fgets(header, 1024, fp);
     693           2 :         if (header[0] != '#') {
     694           2 :             ++line;
     695             :         }
     696             :     }
     697             :     // read width and height
     698           1 :     sscanf(header,"%d %d\n", width, height);
     699             :  
     700             :     // read the maximum of pixels
     701           1 :     fgets(header, 20, fp);
     702             :  
     703             :     // get rgb data
     704           1 :     unsigned char *rgb = new unsigned char [ (*width)*(*height)*3 ];
     705           1 :     fread(rgb, (*width)*(*height)*3, 1, fp);
     706             : 
     707           1 :     *data = new unsigned int [ (*width)*(*height)*4 ];
     708           1 :     int k = 0;
     709        3899 :     for ( int i = 0; i < (*height); i++ ) {
     710    10134800 :         for ( int j = 0; j < (*width); j++ ) {
     711    10130902 :             unsigned char *p = rgb + i*(*width)*3 + j*3;
     712             :                                       // a ( skipped )
     713    10130902 :             (*data)[k]  = p[2] << 16; // r
     714    10130902 :             (*data)[k] |= p[1] << 8;  // g
     715    10130902 :             (*data)[k] |= p[0];       // b
     716    10130902 :             k++;
     717             :         }
     718             :     }
     719             : 
     720             :     // ofc, later, you'll have to cleanup
     721           1 :     delete [] rgb;
     722             :  
     723           1 :     fclose(fp);
     724           1 : }
     725             : 
     726             : //===========================================================================
     727             : /// Load PPM file
     728             : ///
     729             : /// 
     730             : //===========================================================================
     731           1 : int CheckLabelswithPPM(char* filename, int* labels, int width, int height)
     732             : {
     733             :     char header[1024];
     734           1 :     FILE* fp = NULL;
     735           1 :     int line = 0, ground = 0;
     736             :  
     737           1 :     fp = fopen(filename, "rb");
     738             :  
     739             :     // read the image type, such as: P6
     740             :     // skip the comment lines
     741           4 :     while (line < 2) {    
     742           2 :         fgets(header, 1024, fp);
     743           2 :         if (header[0] != '#') {
     744           2 :             ++line;
     745             :         }
     746             :     }
     747             :     // read width and height
     748           1 :         int w(0);
     749           1 :         int h(0);
     750           1 :     sscanf(header,"%d %d\n", &w, &h);
     751           1 :         if (w != width || h != height) return -1;
     752             :  
     753             :     // read the maximum of pixels
     754           1 :     fgets(header, 20, fp);
     755             :  
     756             :     // get rgb data
     757           1 :     unsigned char *rgb = new unsigned char [ (w)*(h)*3 ];
     758           1 :     fread(rgb, (w)*(h)*3, 1, fp);
     759             : 
     760           1 :     int num = 0, k = 0;
     761        3899 :     for ( int i = 0; i < (h); i++ ) {
     762    10134800 :         for ( int j = 0; j < (w); j++ ) {
     763    10130902 :             unsigned char *p = rgb + i*(w)*3 + j*3;
     764             :                                   // a ( skipped )
     765    10130902 :             ground  = p[2] << 16; // r
     766    10130902 :             ground |= p[1] << 8;  // g
     767    10130902 :             ground |= p[0];       // b
     768             :             
     769    10130902 :                         if (ground != labels[k])
     770           0 :                                 num++;
     771             : 
     772    10130902 :                         k++;
     773             :         }
     774             :     }
     775             : 
     776             :     // ofc, later, you'll have to cleanup
     777           1 :     delete [] rgb;
     778             :  
     779           1 :     fclose(fp);
     780             : 
     781           1 :         return num;
     782             : }
     783             : 
     784             : //===========================================================================
     785             : ///     The main function
     786             : ///
     787             : //===========================================================================
     788           1 : int main (int argc, char **argv)
     789             : {
     790           1 :         unsigned int* img = NULL;
     791           1 :         int width(0);
     792           1 :         int height(0);
     793             : 
     794           1 :         LoadPPM((char *)"input_image.ppm", &img, &width, &height);
     795           1 :         if (width == 0 || height == 0) return -1;
     796             : 
     797           1 :         int sz = width*height;
     798           1 :         int* labels = new int[sz];
     799           1 :         int numlabels(0);
     800           1 :         SLIC slic;
     801             :         int m_spcount;
     802             :         double m_compactness;
     803           1 :         m_spcount = 200;
     804           1 :         m_compactness = 10.0;
     805           1 :     auto startTime = Clock::now();
     806           1 :         slic.PerformSLICO_ForGivenK(img, width, height, labels, numlabels, m_spcount, m_compactness);//for a given number K of superpixels
     807           1 :     auto endTime = Clock::now();
     808           1 :     auto compTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime);
     809           1 :     cout <<  "Computing time=" << compTime.count()/1000 << " ms" << endl;
     810             : 
     811           1 :         int num = CheckLabelswithPPM((char *)"check.ppm", labels, width, height);
     812           1 :         if (num < 0) {
     813           0 :                 cout <<  "The result for labels is different from output_labels.ppm." << endl;
     814             :         } else {
     815           1 :                 cout <<  "There are " << num << " points' labels are different from original file." << endl;
     816             :         }
     817             :         
     818           1 :         slic.SaveSuperpixelLabels2PPM((char *)"output_labels.ppm", labels, width, height);
     819           1 :         if(labels) delete [] labels;
     820             :         
     821           1 :         if(img) delete [] img;
     822             : 
     823           1 :         return 0;
     824           3 : }

Generated by: LCOV version 1.13