segment-image.h
Go to the documentation of this file.
00001 /*
00002   Copyright (C) 2006 Pedro Felzenszwalb
00003 
00004   This program is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008 
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details.
00013 
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00017 */
00018 
00019 #ifndef SEGMENT_IMAGE
00020 #define SEGMENT_IMAGE
00021 
00022 #include <cstdlib>
00023 #include "image.h"
00024 #include "misc.h"
00025 #include "filter.h"
00026 #include "segment-graph.h"
00027 
00028 // random color
00029 rgb random_rgb(){
00030   rgb c;
00031   //double r;
00032 
00033   c.r = (uchar)random();
00034   c.g = (uchar)random();
00035   c.b = (uchar)random();
00036 
00037   return c;
00038 }
00039 
00040 // dissimilarity measure between pixels
00041 static inline float diff(image<float> *r, image<float> *g, image<float> *b,
00042                          int x1, int y1, int x2, int y2) {
00043   return sqrt(square(imRef(r, x1, y1)-imRef(r, x2, y2)) +
00044               square(imRef(g, x1, y1)-imRef(g, x2, y2)) +
00045               square(imRef(b, x1, y1)-imRef(b, x2, y2)));
00046 }
00047 
00064 static inline float depth_diff(image<float> *r, image<float> *g,
00065                                image<float> *b, image<float> *d,
00066                                int x1, int y1, int x2, int y2,
00067                                float wr,float wg, float wb, float wd) {
00068   return sqrt(wr*square(imRef(r, x1, y1)-imRef(r, x2, y2)) +
00069               wg*square(imRef(g, x1, y1)-imRef(g, x2, y2)) +
00070               wb*square(imRef(b, x1, y1)-imRef(b, x2, y2)) +
00071               wd*exp(square(imRef(d, x1, y1)-imRef(d, x2, y2))));
00072 }
00073 
00074 /*
00075  * Segment an image
00076  *
00077  * Returns a color image representing the segmentation.
00078  *
00079  * im: image to segment.
00080  * sigma: to smooth the image.
00081  * c: constant for treshold function.
00082  * min_size: minimum component size (enforced by post-processing stage).
00083  * num_ccs: number of connected components in the segmentation.
00084  */
00085 image<rgb> *segment_image(image<rgb> *im, float sigma, float c, int min_size,
00086                           int *num_ccs) {
00087   int width = im->width();
00088   int height = im->height();
00089 
00090   image<float> *r = new image<float>(width, height);
00091   image<float> *g = new image<float>(width, height);
00092   image<float> *b = new image<float>(width, height);
00093 
00094   // smooth each color channel
00095   for (int y = 0; y < height; y++) {
00096     for (int x = 0; x < width; x++) {
00097       imRef(r, x, y) = imRef(im, x, y).r;
00098       imRef(g, x, y) = imRef(im, x, y).g;
00099       imRef(b, x, y) = imRef(im, x, y).b;
00100     }
00101   }
00102   image<float> *smooth_r = smooth(r, sigma);
00103   image<float> *smooth_g = smooth(g, sigma);
00104   image<float> *smooth_b = smooth(b, sigma);
00105   delete r;
00106   delete g;
00107   delete b;
00108 
00109   // build graph
00110   edge *edges = new edge[width*height*4];
00111   int num = 0;
00112   for (int y = 0; y < height; y++) {
00113     for (int x = 0; x < width; x++) {
00114       if (x < width-1) {
00115         edges[num].a = y * width + x;
00116         edges[num].b = y * width + (x+1);
00117         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y);
00118         num++;
00119       }
00120 
00121       if (y < height-1) {
00122         edges[num].a = y * width + x;
00123         edges[num].b = (y+1) * width + x;
00124         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1);
00125         num++;
00126       }
00127 
00128       if ((x < width-1) && (y < height-1)) {
00129         edges[num].a = y * width + x;
00130         edges[num].b = (y+1) * width + (x+1);
00131         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1);
00132         num++;
00133       }
00134 
00135       if ((x < width-1) && (y > 0)) {
00136         edges[num].a = y * width + x;
00137         edges[num].b = (y-1) * width + (x+1);
00138         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1);
00139         num++;
00140       }
00141     }
00142   }
00143   delete smooth_r;
00144   delete smooth_g;
00145   delete smooth_b;
00146 
00147   // segment
00148   universe *u = segment_graph(width*height, num, edges, c);
00149 
00150   // post process small components
00151   for (int i = 0; i < num; i++) {
00152     int a = u->find(edges[i].a);
00153     int b = u->find(edges[i].b);
00154     if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
00155       u->join(a, b);
00156   }
00157   delete [] edges;
00158   *num_ccs = u->num_sets();
00159 
00160   image<rgb> *output = new image<rgb>(width, height);
00161 
00162   // pick random colors for each component
00163   rgb *colors = new rgb[width*height];
00164 
00165   // Added by MWF
00166   int *segmentids = new int[width*height];
00167   int segmentcounter = 1;
00168   // end MWF addition
00169 
00170   for (int i = 0; i < width*height; i++) {
00171     colors[i] = random_rgb();
00172     segmentids[i] = 0;
00173   }
00174 
00175   for (int y = 0; y < height; y++) {
00176     for (int x = 0; x < width; x++) {
00177       int comp = u->find(y * width + x);
00178       imRef(output, x, y) = colors[comp];
00179       // Added by MWF, 9/22/08
00180       // If we encounter a new comp / segment, record
00181       // its segmentid and increment the segmentid counter
00182       if (segmentids[comp] == 0)
00183       {
00184         segmentids[comp] = segmentcounter;
00185         segmentcounter++;
00186       }
00187       imRef(output, x, y).idx = segmentids[comp];
00188       // end MWF addition
00189     }
00190   }
00191 
00192   delete [] colors;
00193   delete u;
00194 
00195   return output;
00196 }
00197 
00198 /*
00199  * Segment an image
00200  *
00201  * Returns a color image representing the segmentation.
00202  *
00203  * im: image to segment.
00204  * sigma: to smooth the image.
00205  * c: constant for treshold function.
00206  * min_size: minimum component size (enforced by post-processing stage).
00207  * num_ccs: number of connected components in the segmentation.
00208  * wc: weight on each color channel
00209  * wd: weight on the depth channel
00210  */
00211 image<rgb> *segment_image(image<rgb> *color_im, image<float> *depth_im,
00212                           float sigma, float c, int min_size, int *num_ccs,
00213                           float wr, float wg, float wb, float wd) {
00214   int width = color_im->width();
00215   int height = color_im->height();
00216 
00217   image<float> *r = new image<float>(width, height);
00218   image<float> *g = new image<float>(width, height);
00219   image<float> *b = new image<float>(width, height);
00220   image<float> *d = new image<float>(width, height);
00221 
00222   // smooth each color channel
00223   for (int y = 0; y < height; y++) {
00224     for (int x = 0; x < width; x++) {
00225       imRef(r, x, y) = imRef(color_im, x, y).r;
00226       imRef(g, x, y) = imRef(color_im, x, y).g;
00227       imRef(b, x, y) = imRef(color_im, x, y).b;
00228       imRef(d, x, y) = imRef(depth_im, x, y);
00229     }
00230   }
00231   image<float> *smooth_r = smooth(r, sigma);
00232   image<float> *smooth_g = smooth(g, sigma);
00233   image<float> *smooth_b = smooth(b, sigma);
00234   image<float> *smooth_d = smooth(d, sigma);
00235   delete r;
00236   delete g;
00237   delete b;
00238   delete d;
00239 
00240   // build graph
00241   edge *edges = new edge[width*height*4];
00242   int num = 0;
00243   for (int y = 0; y < height; y++) {
00244     for (int x = 0; x < width; x++) {
00245       if (x < width-1) {
00246         edges[num].a = y * width + x;
00247         edges[num].b = y * width + (x+1);
00248         edges[num].w = depth_diff(smooth_r, smooth_g, smooth_b, smooth_d, x, y,
00249                                   x+1, y, wr, wg, wb, wd);
00250         num++;
00251       }
00252 
00253       if (y < height-1) {
00254         edges[num].a = y * width + x;
00255         edges[num].b = (y+1) * width + x;
00256         edges[num].w = depth_diff(smooth_r, smooth_g, smooth_b, smooth_d, x, y,
00257                                   x, y+1, wr, wg, wb, wd);
00258         num++;
00259       }
00260 
00261       if ((x < width-1) && (y < height-1)) {
00262         edges[num].a = y * width + x;
00263         edges[num].b = (y+1) * width + (x+1);
00264         edges[num].w = depth_diff(smooth_r, smooth_g, smooth_b, smooth_d, x, y,
00265                                   x+1, y+1, wr, wg, wb, wd);
00266         num++;
00267       }
00268 
00269       if ((x < width-1) && (y > 0)) {
00270         edges[num].a = y * width + x;
00271         edges[num].b = (y-1) * width + (x+1);
00272         edges[num].w = depth_diff(smooth_r, smooth_g, smooth_b, smooth_d, x, y,
00273                                   x+1, y-1, wr, wg, wb, wd);
00274         num++;
00275       }
00276     }
00277   }
00278   delete smooth_r;
00279   delete smooth_g;
00280   delete smooth_b;
00281   delete smooth_d;
00282 
00283   // segment
00284   universe *u = segment_graph(width*height, num, edges, c);
00285 
00286   // post process small components
00287   for (int i = 0; i < num; i++) {
00288     int a = u->find(edges[i].a);
00289     int b = u->find(edges[i].b);
00290     if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
00291       u->join(a, b);
00292   }
00293   delete [] edges;
00294   *num_ccs = u->num_sets();
00295 
00296   image<rgb> *output = new image<rgb>(width, height);
00297 
00298   // pick random colors for each component
00299   rgb *colors = new rgb[width*height];
00300 
00301   // Added by MWF
00302   int *segmentids = new int[width*height];
00303   int segmentcounter = 1;
00304   // end MWF addition
00305 
00306   for (int i = 0; i < width*height; i++) {
00307     colors[i] = random_rgb();
00308     segmentids[i] = 0;
00309   }
00310 
00311   for (int y = 0; y < height; y++) {
00312     for (int x = 0; x < width; x++) {
00313       int comp = u->find(y * width + x);
00314       imRef(output, x, y) = colors[comp];
00315       // Added by MWF, 9/22/08
00316       // If we encounter a new comp / segment, record
00317       // its segmentid and increment the segmentid counter
00318       if (segmentids[comp] == 0)
00319       {
00320         segmentids[comp] = segmentcounter;
00321         segmentcounter++;
00322       }
00323       imRef(output, x, y).idx = segmentids[comp];
00324       // end MWF addition
00325     }
00326   }
00327 
00328   delete [] colors;
00329   delete u;
00330 
00331   return output;
00332 }
00333 
00334 #endif


cpl_superpixels
Author(s): Tucker Hermans
autogenerated on Wed Nov 27 2013 11:38:57