头文件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