-
Notifications
You must be signed in to change notification settings - Fork 4
/
SLIC.h
318 lines (301 loc) · 12.1 KB
/
SLIC.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// SLIC.h: interface for the SLIC class.
//===========================================================================
// This code implements the saliency method described in:
//
// Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk,
// "SLIC Superpixels",
// EPFL Technical Report no. 149300, June 2010.
//===========================================================================
// Copyright (c) 2010 Radhakrishna Achanta [EPFL]. All rights reserved.
//===========================================================================
// Email: [email protected]
//////////////////////////////////////////////////////////////////////
#ifndef _SLIC_H_INCLUDED_
#define _SLIC_H_INCLUDED_
#include <vector>
#include <string>
#include <algorithm>
#ifndef SLIC_MAX
#define SLIC_MAX(a,b) ((a>b)?a:b)
#endif
#ifndef SLIC_MIN
#define SLIC_MIN(a,b) ((a<b)?a:b)
#endif
// Longest number of characters in a file name.
#define _MAX_FNAME 128
/*! \brief Just do the damn segmentation.
* \author Philip G. Lee
*
* \param labels width*height*sizeof(int) row-major buffer for the pixel labels
* \param in width*height*sizeof(unsigned int) row-major ARGB pixel buffer
* \param width width of input image and output labels
* \param height height of input image and output labels
* \param nseg approximate number of output segments
* \param spatialConsistency higher means segments are more spatially smooth and regular.
* \returns the number of segments produced
*/
int slicSegmentation( int* labels, const unsigned int* in, int width, int height, int nseg, double spatialConsistency = 10.0 );
class SLIC
{
public:
SLIC();
virtual ~SLIC();
/*!
* Superpixel segmentation for a given step size (superpixel size ~= step*step)
* INPUT:
* \b ubuff - argb array in raster-scan order representing the image.
* \b width - image width
* \b height - image height
* \b STEP - step size. Each superpixel will be approximately STEPxSTEP.
* \b m - Parameter (>0) controlling spatial consistency?
* OUTPUT:
* \b klabels - appears to be an image of the labels
* \b numlabels - number of labels
*/
void DoSuperpixelSegmentation_ForGivenStepSize(
const unsigned int* ubuff,//Each 32 bit unsigned int contains ARGB pixel values.
const int width,
const int height,
int** klabels,
int& numlabels,
const int& STEP,
const double& m);
//============================================================================
// Superpixel segmentation for a given number of superpixels
//============================================================================
void DoSuperpixelSegmentation_ForGivenK(
const unsigned int* ubuff,
const int width,
const int height,
int* klabels,
int& numlabels,
const int& K,
const double& m);
//============================================================================
// Supervoxel segmentation for a given step size (supervoxel size ~= step*step*step)
//============================================================================
void DoSupervoxelSegmentation(
const unsigned int** ubuffvec,
const int& width,
const int& height,
const int& depth,
int** klabels,
int& numlabels, const int& STEP,
const double& m);
//============================================================================
// Save superpixel labels in a text file in raster scan order
//============================================================================
void SaveSuperpixelLabels(
const int*& labels,
const int& width,
const int& height,
const std::string& filename,
const std::string& path);
//============================================================================
// Save superpixel labels in a text file in raster scan, depth order
//============================================================================
void SaveSupervoxelLabels(
const int**& labels,
const int& width,
const int& height,
const int& depth,
const std::string& filename,
const std::string& path);
//============================================================================
// Function to draw boundaries around superpixels of a given 'color'.
// Can also be used to draw boundaries around supervoxels, i.e layer by layer.
//============================================================================
void DrawContoursAroundSegments(
unsigned int* segmentedImage,
const int* labels,
const int& width,
const int& height,
const unsigned int& color );
private:
//============================================================================
// The main SLIC algorithm for generating superpixels
//============================================================================
void PerformSuperpixelSLIC(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
int* klabels,
const int& STEP,
const std::vector<double>& edgemag,
const double& m);
//============================================================================
// The main SLIC algorithm for generating supervoxels
//============================================================================
void PerformSupervoxelSLIC(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
std::vector<double>& kseedsz,
int** klabels,
const int& STEP,
const double& m);
//============================================================================
// Pick seeds for superpixels when step size of superpixels is given.
//============================================================================
void GetLABXYSeeds_ForGivenStepSize(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
const int& STEP,
const bool& perturbseeds,
const std::vector<double>& edgemag);
//============================================================================
// Pick seeds for superpixels when number of superpixels is input.
//============================================================================
void GetLABXYSeeds_ForGivenK(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
const int& STEP,
const bool& perturbseeds,
const std::vector<double>& edges);
//============================================================================
// Pick seeds for supervoxels
//============================================================================
void GetKValues_LABXYZ(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
std::vector<double>& kseedsz,
const int& STEP);
//============================================================================
// Move the seeds to low gradient positions to avoid putting seeds at region boundaries.
//============================================================================
void PerturbSeeds(
std::vector<double>& kseedsl,
std::vector<double>& kseedsa,
std::vector<double>& kseedsb,
std::vector<double>& kseedsx,
std::vector<double>& kseedsy,
const std::vector<double>& edges);
//============================================================================
// Detect color edges, to help PerturbSeeds()
//============================================================================
void DetectLabEdges(
const double* lvec,
const double* avec,
const double* bvec,
const int& width,
const int& height,
std::vector<double>& edges);
//============================================================================
// xRGB to XYZ conversion; helper for RGB2LAB()
//============================================================================
void RGB2XYZ(
const int& sR,
const int& sG,
const int& sB,
double& X,
double& Y,
double& Z);
//============================================================================
// sRGB to CIELAB conversion
//============================================================================
void RGB2LAB(
const int& sR,
const int& sG,
const int& sB,
double& lval,
double& aval,
double& bval);
//============================================================================
// sRGB to CIELAB conversion for 2-D images
//============================================================================
void DoRGBtoLABConversion(
const unsigned int*& ubuff,
double*& lvec,
double*& avec,
double*& bvec);
//============================================================================
// sRGB to CIELAB conversion for 3-D volumes
//============================================================================
void DoRGBtoLABConversion(
const unsigned int**& ubuff,
double**& lvec,
double**& avec,
double**& bvec);
//============================================================================
// Post-processing of SLIC segmentation, to avoid stray labels.
//============================================================================
void EnforceLabelConnectivity(
const int* labels,
const int& width,
const int& height,
int* nlabels,//input labels that need to be corrected to remove stray labels
int& numlabels,//the number of labels changes in the end if segments are removed
const int& K); //the number of superpixels desired by the user
//============================================================================
// Find next superpixel label; helper for EnforceLabelConnectivity()
//============================================================================
void FindNext(
const int* labels,
int* nlabels,
const int& height,
const int& width,
const int& h,
const int& w,
const int& lab,
int* xvec,
int* yvec,
int& count);
//============================================================================
// Post-processing of SLIC supervoxel segmentation, to avoid stray labels.
//============================================================================
void EnforceLabelConnectivity_supervoxels(
const int& width,
const int& height,
const int& depth,
int** nlabels,//input labels that to be corrected. output is stored in here too.
int& numlabels,//the number of labels changes in the end if segments are removed
const int& STEP); //step size, it helps decide the minimum acceptable size
//============================================================================
// Find next supervoxel label; helper for EnforceLabelConnectivity()
//============================================================================
void FindNext_supervoxels(
int** labels,
int** nlabels,
const int& depth,
const int& height,
const int& width,
const int& d,
const int& h,
const int& w,
const int& lab,
int* xvec,
int* yvec,
int* zvec,
int& count);
/*!
* \author Philip G. Lee
* Given path = "/path/to/file.ext", returns
* file = "/path/to/file"
* extension = ".ext"
*/
void splitpath( const char* path, char* file, char* extension );
private:
int m_width;
int m_height;
int m_depth;
double* m_lvec;
double* m_avec;
double* m_bvec;
double** m_lvecvec;
double** m_avecvec;
double** m_bvecvec;
};
#endif // _SLIC_H_INCLUDED_