segment-image.h

00001 #ifndef SEGMENT_IMAGE
00002 #define SEGMENT_IMAGE
00003 
00004 #include <cstdlib>
00005 #include <image.h>
00006 #include <misc.h>
00007 #include <filter.h>
00008 #include "segment-graph.h"
00009 #include "CImageSegmentationIndexFile.cpp"
00010 #include <map>
00011 
00012 using namespace segmentation;
00013 // random color
00014 rgb random_rgb(){ 
00015   rgb c;
00016   double r;
00017   
00018   c.r = (uchar)random();
00019   c.g = (uchar)random();
00020   c.b = (uchar)random();
00021 
00022   return c;
00023 }
00024 
00025 // dissimilarity measure between pixels
00026 static inline float diff(image<float> *r, image<float> *g, image<float> *b,
00027                          int x1, int y1, int x2, int y2) {
00028   return sqrt(square(imRef(r, x1, y1)-imRef(r, x2, y2)) +
00029               square(imRef(g, x1, y1)-imRef(g, x2, y2)) +
00030               square(imRef(b, x1, y1)-imRef(b, x2, y2)));
00031 }
00032 
00033 /*
00034  * Segment an image
00035  *
00036  * Returns a color image representing the segmentation.
00037  *
00038  * im: image to segment.
00039  * sigma: to smooth the image.
00040  * c: constant for treshold function.
00041  * min_size: minimum component size (enforced by post-processing stage).
00042  * num_ccs: number of connected components in the segmentation.
00043  */
00044 image<rgb> *segment_image(image<rgb> *im, float sigma, float c, int min_size,
00045                           int *num_ccs, long int bsi[]) {
00046   int width = im->width();
00047   int height = im->height();
00048 
00049   image<float> *r = new image<float>(width, height);
00050   image<float> *g = new image<float>(width, height);
00051   image<float> *b = new image<float>(width, height);
00052 
00053   // smooth each color channel  
00054   for (int y = 0; y < height; y++) {
00055     for (int x = 0; x < width; x++) {
00056       imRef(r, x, y) = imRef(im, x, y).r;
00057       imRef(g, x, y) = imRef(im, x, y).g;
00058       imRef(b, x, y) = imRef(im, x, y).b;
00059     }
00060   }
00061   image<float> *smooth_r = smooth(r, sigma);
00062   image<float> *smooth_g = smooth(g, sigma);
00063   image<float> *smooth_b = smooth(b, sigma);
00064   delete r;
00065   delete g;
00066   delete b;
00067  
00068   // build graph
00069   edge *edges = new edge[width*height*4];
00070   int num = 0;
00071   for (int y = 0; y < height; y++) {
00072     for (int x = 0; x < width; x++) {
00073       if (x < width-1) {
00074         edges[num].a = y * width + x;
00075         edges[num].b = y * width + (x+1);
00076         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y);
00077         num++;
00078       }
00079 
00080       if (y < height-1) {
00081         edges[num].a = y * width + x;
00082         edges[num].b = (y+1) * width + x;
00083         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1);
00084         num++;
00085       }
00086 
00087       if ((x < width-1) && (y < height-1)) {
00088         edges[num].a = y * width + x;
00089         edges[num].b = (y+1) * width + (x+1);
00090         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1);
00091         num++;
00092       }
00093 
00094       if ((x < width-1) && (y > 0)) {
00095         edges[num].a = y * width + x;
00096         edges[num].b = (y-1) * width + (x+1);
00097         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1);
00098         num++;
00099       }
00100     }
00101   }
00102   delete smooth_r;
00103   delete smooth_g;
00104   delete smooth_b;
00105 
00106   // segment
00107   universe *u = segment_graph(width*height, num, edges, c);
00108   
00109   // post process small components
00110   for (int i = 0; i < num; i++) {
00111     int a = u->find(edges[i].a);
00112     int b = u->find(edges[i].b);
00113     if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
00114       u->join(a, b);
00115   }
00116   delete [] edges;
00117   *num_ccs = u->num_sets();
00118 
00119   image<rgb> *output = new image<rgb>(width, height);
00120 
00121   // pick random colors for each component
00122   rgb *colors = new rgb[width*height];
00123   for (int i = 0; i < width*height; i++)
00124     colors[i] = random_rgb();
00125   
00126   std::map<int, int> indices;
00127   int ind=0;
00128 
00129   for (int y = 0; y < height; y++) {
00130     for (int x = 0; x < width; x++) {
00131       int comp = u->find(y * width + x);
00132       if (indices.find(comp) == indices.end()) { // map comp values to lower values
00133         bsi[y * width + x] = ind;
00134         indices[comp] = ind;
00135         ind++;
00136       }
00137       else {
00138         bsi[y * width + x] = indices[comp];
00139       }
00140       if (y != height && x != width)  // was in the orignal code that way, don't know exactly why (??border??)
00141         imRef(output, x, y) = colors[comp];
00142     }
00143   }  
00144 
00145   delete [] colors;  
00146   delete u;
00147 
00148   return output;
00149 }
00150 
00151 #endif

Generated on Thu Jun 22 14:47:19 2006 for ncut.kdevelop by  doxygen 1.4.6