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
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
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
00035
00036
00037
00038
00039
00040
00041
00042
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
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
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
00107 universe *u = segment_graph(width*height, num, edges, c);
00108
00109
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
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()) {
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)
00141 imRef(output, x, y) = colors[comp];
00142 }
00143 }
00144
00145 delete [] colors;
00146 delete u;
00147
00148 return output;
00149 }
00150
00151 #endif