Guest User

Untitled

a guest
Apr 25th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.31 KB | None | 0 0
  1. /*
  2. Copyright (C) 2006 Pedro Felzenszwalb
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. */
  15.  
  16. #ifndef SEGMENT_IMAGE
  17. #define SEGMENT_IMAGE
  18.  
  19. #include <cstdlib>
  20. #include <image.h>
  21. #include <misc.h>
  22. #include <filter.h>
  23. #include "segment-graph.h"
  24. #include <map>
  25.  
  26. // random color
  27. rgb random_rgb(){
  28. rgb c;
  29. double r;
  30.  
  31. c.r = (uchar)random();
  32. c.g = (uchar)random();
  33. c.b = (uchar)random();
  34.  
  35. return c;
  36. }
  37.  
  38. // dissimilarity measure between pixels
  39. static inline float diff(image<float> *r, image<float> *g, image<float> *b,
  40. int x1, int y1, int x2, int y2) {
  41. return sqrt(square(imRef(r, x1, y1)-imRef(r, x2, y2)) +
  42. square(imRef(g, x1, y1)-imRef(g, x2, y2)) +
  43. square(imRef(b, x1, y1)-imRef(b, x2, y2)));
  44. }
  45.  
  46. /*
  47. * Segment an image
  48. *
  49. * Returns a color image representing the segmentation.
  50. *
  51. * im: image to segment.
  52. * sigma: to smooth the image.
  53. * c: constant for treshold function.
  54. * min_size: minimum component size (enforced by post-processing stage).
  55. * num_ccs: number of connected components in the segmentation.
  56. */
  57. image<rgb> *segment_image(image<rgb> *im, float sigma, float c, int min_size,
  58. int *num_ccs) {
  59. int width = im->width();
  60. int height = im->height();
  61.  
  62. image<float> *r = new image<float>(width, height);
  63. image<float> *g = new image<float>(width, height);
  64. image<float> *b = new image<float>(width, height);
  65.  
  66. // smooth each color channel
  67. for (int y = 0; y < height; y++) {
  68. for (int x = 0; x < width; x++) {
  69. imRef(r, x, y) = imRef(im, x, y).r;
  70. imRef(g, x, y) = imRef(im, x, y).g;
  71. imRef(b, x, y) = imRef(im, x, y).b;
  72. }
  73. }
  74. image<float> *smooth_r = smooth(r, sigma);
  75. image<float> *smooth_g = smooth(g, sigma);
  76. image<float> *smooth_b = smooth(b, sigma);
  77. delete r;
  78. delete g;
  79. delete b;
  80.  
  81. // build graph
  82. edge *edges = new edge[width*height*4];
  83. int num = 0;
  84. for (int y = 0; y < height; y++) {
  85. for (int x = 0; x < width; x++) {
  86. if (x < width-1) {
  87. edges[num].a = y * width + x;
  88. edges[num].b = y * width + (x+1);
  89. edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y);
  90. num++;
  91. }
  92.  
  93. if (y < height-1) {
  94. edges[num].a = y * width + x;
  95. edges[num].b = (y+1) * width + x;
  96. edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1);
  97. num++;
  98. }
  99.  
  100. if ((x < width-1) && (y < height-1)) {
  101. edges[num].a = y * width + x;
  102. edges[num].b = (y+1) * width + (x+1);
  103. edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1);
  104. num++;
  105. }
  106.  
  107. if ((x < width-1) && (y > 0)) {
  108. edges[num].a = y * width + x;
  109. edges[num].b = (y-1) * width + (x+1);
  110. edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1);
  111. num++;
  112. }
  113. }
  114. }
  115. delete smooth_r;
  116. delete smooth_g;
  117. delete smooth_b;
  118.  
  119. // segment
  120. Universe *u = segment_graph(width*height, num, edges, c);
  121.  
  122. // post process small components
  123. for (int i = 0; i < num; i++) {
  124. int a = u->find(edges[i].a);
  125. int b = u->find(edges[i].b);
  126. if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
  127. u->join(a, b);
  128. }
  129. delete [] edges;
  130. *num_ccs = u->num_sets();
  131.  
  132. image<rgb> *output = new image<rgb>(width, height);
  133.  
  134.  
  135. // pick random colors for each component
  136. std::map<int, float> average_r;
  137. std::map<int, float> average_g;
  138. std::map<int, float> average_b;
  139.  
  140. std::map<int, int> nb_pixels;
  141.  
  142. for (int y = 0; y < height; y++) {
  143. for (int x = 0; x < width; x++) {
  144. int comp = u->find(y * width + x);
  145.  
  146. average_r[comp] += imRef(im, x, y).r;
  147. average_g[comp] += imRef(im, x, y).g;
  148. average_b[comp] += imRef(im, x, y).b;
  149. nb_pixels[comp]++;
  150.  
  151.  
  152.  
  153. }
  154. }
  155.  
  156. std::map<int, rgb> component_colors;
  157. for( std::map<int, int>::iterator it = nb_pixels.begin() ; it != nb_pixels.end() ; it++ ){
  158. rgb color;
  159. int comp = it->first;
  160.  
  161. color.r = int(float(average_r[comp])/nb_pixels[comp]);
  162. color.g = int(float(average_g[comp])/nb_pixels[comp]);
  163. color.b = int(float(average_b[comp])/nb_pixels[comp]);
  164.  
  165. component_colors[comp] = color;
  166. }
  167.  
  168. for (int y = 0; y < height; y++) {
  169. for (int x = 0; x < width; x++) {
  170. int comp = u->find(y * width + x);
  171.  
  172. imRef(output, x, y) = component_colors[comp];
  173. }
  174. }
  175.  
  176. delete u;
  177.  
  178. return output;
  179. }
  180.  
  181. #endif
Add Comment
Please, Sign In to add comment