00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00029 rgb random_rgb(){
00030 rgb c;
00031
00032
00033 c.r = (uchar)random();
00034 c.g = (uchar)random();
00035 c.b = (uchar)random();
00036
00037 return c;
00038 }
00039
00040
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
00076
00077
00078
00079
00080
00081
00082
00083
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
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
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
00148 universe *u = segment_graph(width*height, num, edges, c);
00149
00150
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
00163 rgb *colors = new rgb[width*height];
00164
00165
00166 int *segmentids = new int[width*height];
00167 int segmentcounter = 1;
00168
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
00180
00181
00182 if (segmentids[comp] == 0)
00183 {
00184 segmentids[comp] = segmentcounter;
00185 segmentcounter++;
00186 }
00187 imRef(output, x, y).idx = segmentids[comp];
00188
00189 }
00190 }
00191
00192 delete [] colors;
00193 delete u;
00194
00195 return output;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
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
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
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
00284 universe *u = segment_graph(width*height, num, edges, c);
00285
00286
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
00299 rgb *colors = new rgb[width*height];
00300
00301
00302 int *segmentids = new int[width*height];
00303 int segmentcounter = 1;
00304
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
00316
00317
00318 if (segmentids[comp] == 0)
00319 {
00320 segmentids[comp] = segmentcounter;
00321 segmentcounter++;
00322 }
00323 imRef(output, x, y).idx = segmentids[comp];
00324
00325 }
00326 }
00327
00328 delete [] colors;
00329 delete u;
00330
00331 return output;
00332 }
00333
00334 #endif