PICCANTE  0.4
The hottest HDR imaging library!
superpixels_slic.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_ALGORITHMS_SUPERPIXELS_SLIC_HPP
19 #define PIC_ALGORITHMS_SUPERPIXELS_SLIC_HPP
20 
21 #include "../image.hpp"
22 #include "../filtering/filter_laplacian.hpp"
23 
24 namespace pic {
25 
29 struct SlicoCenter {
30  float *value;
31  unsigned int x, y;
32 };
33 
37 class Slic
38 {
39 protected:
40 
44  unsigned int *prevX, *prevY, *counter;
45  float *col_values, *mPixel;
47 
55  inline float distanceC(float *a1, float *a2, int channels)
56  {
57  float acc = 0.0f;
58 
59  for(int i = 0; i < channels; i++) {
60  float tmp = (a1[i] - a2[i]);
61  acc += tmp * tmp;
62  }
63 
64  return acc;
65  }
66 
75  inline int distanceS(int x1, int y1, int x2, int y2)
76  {
77  int tx = x1 - x2;
78  int ty = y1 - y2;
79  return tx * tx + ty * ty;
80  }
81 
88  bool pass(Image *img, int S)
89  {
90  float Sf = float(S);
91  float Sf2 = Sf * Sf;
92 
93  for(int i = 0; i < nSuperPixels; i++) {
94  prevX[i] = centers[i].x;
95  prevY[i] = centers[i].y;
96  }
97 
98  //for each cluster
99  for(int i = 0; i < nSuperPixels; i++) {
100  float i_f = float(i);
101 
102  //Search in Sx2 radius
103  for(int j = -S; j < S; j++) {
104  int vY = centers[i].y + j;
105 
106  for(int k = -S; k < S; k++) {
107  int vX = centers[i].x + k;
108 
109  float *pixel = (*img)(vX, vY);
110  float *l_d = (*labels_distance)(vX, vY);
111 
112  float dS = float(distanceS(vX, vY, centers[i].x, centers[i].y)) / Sf2;
113  float dC = distanceC(pixel, centers[i].value, img->channels) / mPixel[i];
114  float D = dC + dS;
115 
116  if(D < l_d[1]) {
117  l_d[0] = i_f;
118  l_d[1] = D;
119  l_d[2] = dC;
120  }
121  }
122  }
123  }
124 
125  //update mPixel
126  for(int i = 0; i < labels_distance->size(); i += labels_distance->channels) {
127  int label = int(labels_distance->data[i]);
128 
129  if(label < 0) {
130  continue;
131  }
132 
133  if(mPixel[label] < labels_distance->data[i + 2]) {
134  mPixel[label] = labels_distance->data[i + 2];
135  }
136  }
137 
138  //update clusters
139  for(int i = 0; i < nSuperPixels; i++) {
140  centers[i].x = 0;
141  centers[i].y = 0;
142  counter[i] = 0;
143 
144  int ind = i * img->channels;
145 
146  for(int j = 0; j < img->channels; j++) {
147  col_values[ind + j] = 0.0f;
148  }
149  }
150 
151  for(int j = 0; j < img->height; j++) {
152  for(int k = 0; k < img->width; k++) {
153  float *l_d = (*labels_distance)(k, j);
154  int label = int(l_d[0]);
155 
156  if(label > -1) {
157  centers[label].x += k;
158  centers[label].y += j;
159  counter[label]++;
160 
161  int ind = label * img->channels;
162  float *col = (*img)(k, j);
163 
164  for(int p = 0; p < img->channels; p++) {
165  col_values[ind + p] += col[p];
166  }
167  }
168  }
169  }
170 
171  float E = 0.0f;
172 
173  for(int i = 0; i < nSuperPixels; i++) {
174  if(counter[i] <= 0) {
175  continue;
176  }
177 
178  centers[i].x /= counter[i];
179  centers[i].y /= counter[i];
180  int ind = i * img->channels;
181 
182  for(int j = 0; j < img->channels; j++) {
183  centers[i].value[j] = col_values[ind + j] / float(counter[i]);
184  }
185 
186  //Error
187  int tx = prevX[i] - centers[i].x;
188  int ty = prevY[i] - centers[i].y;
189  float tmpErr = sqrtf(float(tx * tx + ty * ty));
190  E += tmpErr;
191  }
192 
193  return (E > (0.0001f * float(nSuperPixels)));
194  }
195 
196 
197 
204  {
205 
206  this->nSuperPixels = nSuperPixels;
207 
208  release();
209 
211  prevX = new unsigned int [nSuperPixels];
212  prevY = new unsigned int [nSuperPixels];
213  counter = new unsigned int [nSuperPixels];
214  mPixel = new float [nSuperPixels];
215  col_values = new float [nSuperPixels * channels];
216  }
217 
221  void release()
222  {
223  if(lap_img != NULL) {
224  delete lap_img;
225  }
226 
227  if(labels_distance != NULL) {
228  delete labels_distance;
229  }
230 
231  if(centers != NULL) {
232  delete[] centers;
233  }
234 
235  if(prevX != NULL) {
236  delete[] prevX;
237  }
238 
239  if(prevY != NULL) {
240  delete[] prevY;
241  }
242 
243  if(counter != NULL) {
244  delete[] counter;
245  }
246 
247  if(col_values != NULL) {
248  delete[] col_values;
249  }
250 
251  if(mPixel != NULL) {
252  delete[] mPixel;
253  }
254  }
255 
256 public:
257 
262  {
263  lap_img = NULL;
264  labels_distance = NULL;
265  centers = NULL;
266  prevX = NULL;
267  prevY = NULL;
268  counter = NULL;
269  col_values = NULL;
270  mPixel = NULL;
271  }
272 
278  Slic(Image *img, int nSuperPixels = 64)
279  {
280  lap_img = NULL;
281  labels_distance = NULL;
282  centers = NULL;
283  prevX = NULL;
284  prevY = NULL;
285  counter = NULL;
286  col_values = NULL;
287  mPixel = NULL;
288 
289  execute(img, nSuperPixels);
290  }
291 
293  {
294  release();
295  }
296 
302  void execute(Image *img, int nSuperPixels = 64)
303  {
304  if(img == NULL) {
305  return;
306  }
307 
308  //Init
309  int S = int(sqrtf(img->widthf * img->heightf) / float(nSuperPixels));
310 
311  if(S < 1) {
312  return;
313  }
314 
315  nSuperPixels = (img->width / S) * (img->height / S);
316 
318 
319  if(labels_distance == NULL) {
320  labels_distance = new Image(1, img->width, img->height, 3);
321  }
322 
323  for(int i = 0; i < labels_distance->size(); i += labels_distance->channels) {
324  labels_distance->data[i ] = -1.0f;
325  labels_distance->data[i + 1] = FLT_MAX;
326  labels_distance->data[i + 2] = FLT_MAX;
327  }
328 
329  width = img->width;
330  height = img->height;
331  channels = img->channels;
332 
333  FilterLaplacian lap;
334  lap_img = lap.Process(Single(img), lap_img);
335 
336  for(int i = 0; i < nSuperPixels; i++) {
337  mPixel[i] = 0.35f * 0.35f; //10.0f*10.0f;
338  }
339 
340  #ifdef PIC_DEBUG
341  printf("nSuperPixels: %d S: %d\n", nSuperPixels, S);
342  #endif
343 
344  int ind = 0;
345  int S_half = S >> 1;
346 
347  for(int i = S_half; i < (img->height - S_half + 1); i += S) {
348  for(int j = S_half; j < (img->width - S_half + 1); j += S) {
349 
350  float bValue = FLT_MAX;
351  int bX, bY;
352 
353  for(int y = -1; y <= 1; y++) {
354  for(int x = -1; x <= 1; x++) {
355  int ix = (j + x);
356  int iy = (i + y);
357  float *data = (*lap_img)(ix, iy);
358 
359  float acc = 0.0f;
360 
361  for(int c = 0; c < img->channels; c++) {
362  acc += fabsf(data[c]);
363  }
364 
365  if(acc < bValue) {
366  bValue = acc;
367  bX = ix;
368  bY = iy;
369  }
370  }
371  }
372 
373  centers[ind].x = bX;
374  centers[ind].y = bY;
375  centers[ind].value = new float [img->channels];
376 
377  BBox box(centers[ind].x - S_half, centers[ind].x + S_half + 1,
378  centers[ind].y - S_half, centers[ind].y + S_half + 1);
379 
380  img->getMeanVal(&box, centers[ind].value);
381  ind++;
382  }
383  }
384 
385  //For each pass
386  int iter = 0;
387  bool bCheck = true;
388 
389  while(bCheck) {
390  bCheck = pass(img, S);
391 
392  if(!bCheck && iter <= 10) {
393  bCheck = true;
394  }
395 
396  iter++;
397  }
398 
399  #ifdef PIC_DEBUG
400  printf("Iterations: %d\n", iter);
401  #endif
402  }
403 
409  int *getLabelsBuffer(int *out = NULL)
410  {
411  if(labels_distance == NULL) {
412  return NULL;
413  }
414 
416 
417  if(size < 1) {
418  return NULL;
419  }
420 
421  if(out == NULL) {
422  out = new int[size];
423  }
424 
425  for(int i = 0; i < size; i++) {
426  out[i] = int(labels_distance->data[i << 1]);
427  }
428 
429  return out;
430  }
431 
438  {
439  if(imgOut == NULL) {
440  imgOut = new Image(1, width, height, channels);
441  }
442 
443  for(int i = 0; i < height; i++) {
444  for(int j = 0; j < width; j++) {
445  float *pixel = (*imgOut)(j, i);
446  float *l_d = (*labels_distance)(j, i);
447 
448  int label = int(l_d[0]);
449 
450  if(label > -1) {
451  for(int k = 0; k < channels; k++) {
452  pixel[k] = centers[label].value[k];
453  }
454  }
455  }
456  }
457 
458  return imgOut;
459  }
460 };
461 
462 } // end namespace pic
463 
464 #endif /* PIC_ALGORITHMS_SUPERPIXELS_SLIC_HPP */
465 
int width
Definition: superpixels_slic.hpp:46
The BBox class manages the creation of bounding boxes for images.
Definition: bbox.hpp:29
int size() const
size computes the number of values.
Definition: image.hpp:481
float * data
data is the main buffer where pixel values are stored.
Definition: image.hpp:91
int channels
Definition: image.hpp:80
float * getMeanVal(BBox *box, float *ret)
getMeanVal computes the mean for the current Image.
The Slic class.
Definition: superpixels_slic.hpp:37
unsigned int * counter
Definition: superpixels_slic.hpp:44
The FilterLaplacian class.
Definition: filter_laplacian.hpp:28
unsigned int y
Definition: superpixels_slic.hpp:31
unsigned int * prevX
Definition: superpixels_slic.hpp:44
unsigned int * prevY
Definition: superpixels_slic.hpp:44
virtual Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter.hpp:390
float heightf
Definition: image.hpp:84
void allocate(int nSuperPixels, int channels)
allocate
Definition: superpixels_slic.hpp:203
Slic(Image *img, int nSuperPixels=64)
Slic.
Definition: superpixels_slic.hpp:278
Slic()
Slic.
Definition: superpixels_slic.hpp:261
unsigned int x
Definition: superpixels_slic.hpp:31
void release()
release
Definition: superpixels_slic.hpp:221
Image * labels_distance
Definition: superpixels_slic.hpp:42
int height
Definition: superpixels_slic.hpp:46
The SlicoCenter struct.
Definition: superpixels_slic.hpp:29
float * col_values
Definition: superpixels_slic.hpp:45
int channels
Definition: superpixels_slic.hpp:46
int distanceS(int x1, int y1, int x2, int y2)
distanceS
Definition: superpixels_slic.hpp:75
float widthf
Definition: image.hpp:84
SlicoCenter * centers
Definition: superpixels_slic.hpp:43
int nSuperPixels
Definition: superpixels_slic.hpp:41
~Slic()
Definition: superpixels_slic.hpp:292
The Image class stores an image as buffer of float.
Definition: image.hpp:60
void execute(Image *img, int nSuperPixels=64)
execute
Definition: superpixels_slic.hpp:302
float * value
Definition: superpixels_slic.hpp:30
bool pass(Image *img, int S)
pass
Definition: superpixels_slic.hpp:88
PIC_INLINE ImageVec Single(Image *img)
Single creates an std::vector which contains img; this is for filters input.
Definition: image_vec.hpp:36
Definition: bilateral_separation.hpp:25
Image * lap_img
Definition: superpixels_slic.hpp:42
int * getLabelsBuffer(int *out=NULL)
getLabelsBuffer
Definition: superpixels_slic.hpp:409
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
float * mPixel
Definition: superpixels_slic.hpp:45
float distanceC(float *a1, float *a2, int channels)
distanceC
Definition: superpixels_slic.hpp:55
Image * getMeanImage(Image *imgOut)
getMeanImage
Definition: superpixels_slic.hpp:437