Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Namespace Members | Data Fields | Globals

segment-image.h

Go to the documentation of this file.
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 
00010 // random color
00011 rgb random_rgb(){ 
00012   rgb c;
00013   double r;
00014   
00015   c.r = (uchar)random();
00016   c.g = (uchar)random();
00017   c.b = (uchar)random();
00018 
00019   return c;
00020 }
00021 
00022 // dissimilarity measure between pixels
00023 static inline float diff(image<float> *r, image<float> *g, image<float> *b,
00024                          int x1, int y1, int x2, int y2) {
00025   return sqrt(square(imRef(r, x1, y1)-imRef(r, x2, y2)) +
00026               square(imRef(g, x1, y1)-imRef(g, x2, y2)) +
00027               square(imRef(b, x1, y1)-imRef(b, x2, y2)));
00028 }
00029 
00030 /*
00031  * Segment an image
00032  *
00033  * Returns a color image representing the segmentation.
00034  *
00035  * im: image to segment.
00036  * sigma: to smooth the image.
00037  * c: constant for treshold function.
00038  * min_size: minimum component size (enforced by post-processing stage).
00039  * num_ccs: number of connected components in the segmentation.
00040  */
00041 image<rgb> *segment_image(image<rgb> *im, float sigma, float c, int min_size,
00042                           int *num_ccs) {
00043   int width = im->width();
00044   int height = im->height();
00045 
00046   image<float> *r = new image<float>(width, height);
00047   image<float> *g = new image<float>(width, height);
00048   image<float> *b = new image<float>(width, height);
00049 
00050   // smooth each color channel  
00051   for (int y = 0; y < height; y++) {
00052     for (int x = 0; x < width; x++) {
00053       imRef(r, x, y) = imRef(im, x, y).r;
00054       imRef(g, x, y) = imRef(im, x, y).g;
00055       imRef(b, x, y) = imRef(im, x, y).b;
00056     }
00057   }
00058   image<float> *smooth_r = smooth(r, sigma);
00059   image<float> *smooth_g = smooth(g, sigma);
00060   image<float> *smooth_b = smooth(b, sigma);
00061   delete r;
00062   delete g;
00063   delete b;
00064  
00065   // build graph
00066   edge *edges = new edge[width*height*4];
00067   int num = 0;
00068   for (int y = 0; y < height; y++) {
00069     for (int x = 0; x < width; x++) {
00070       if (x < width-1) {
00071         edges[num].a = y * width + x;
00072         edges[num].b = y * width + (x+1);
00073         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y);
00074         num++;
00075       }
00076 
00077       if (y < height-1) {
00078         edges[num].a = y * width + x;
00079         edges[num].b = (y+1) * width + x;
00080         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1);
00081         num++;
00082       }
00083 
00084       if ((x < width-1) && (y < height-1)) {
00085         edges[num].a = y * width + x;
00086         edges[num].b = (y+1) * width + (x+1);
00087         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1);
00088         num++;
00089       }
00090 
00091       if ((x < width-1) && (y > 0)) {
00092         edges[num].a = y * width + x;
00093         edges[num].b = (y-1) * width + (x+1);
00094         edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1);
00095         num++;
00096       }
00097     }
00098   }
00099   delete smooth_r;
00100   delete smooth_g;
00101   delete smooth_b;
00102 
00103   // segment
00104   universe *u = segment_graph(width*height, num, edges, c);
00105   
00106   // post process small components
00107   for (int i = 0; i < num; i++) {
00108     int a = u->find(edges[i].a);
00109     int b = u->find(edges[i].b);
00110     if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
00111       u->join(a, b);
00112   }
00113   delete [] edges;
00114   *num_ccs = u->num_sets();
00115 
00116   image<rgb> *output = new image<rgb>(width, height);
00117 
00118   // pick random colors for each component
00119   rgb *colors = new rgb[width*height];
00120   for (int i = 0; i < width*height; i++)
00121     colors[i] = random_rgb();
00122   
00123   for (int y = 0; y < height-1; y++) {
00124     for (int x = 0; x < width-1; x++) {
00125       int comp = u->find(y * width + x);
00126       imRef(output, x, y) = colors[comp];
00127     }
00128   }  
00129 
00130   delete [] colors;  
00131   delete u;
00132 
00133   return output;
00134 }
00135 
00136 #endif

Generated on Wed Oct 5 14:36:12 2005 for RobotFlow by  doxygen 1.4.4