Apollo  6.0
Open source self driving car software
segment_image.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2019 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 /*
18 Copyright (C) 2006 Pedro Felzenszwalb
19 This program is free software; you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation; either version 2 of the License, or
22 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31 
32 #pragma once
33 
34 #include <cstdlib>
35 #include "modules/perception/lidar/detector/ncut_segmentation/common/graph_felzenszwalb/filter.h"
36 #include "modules/perception/lidar/detector/ncut_segmentation/common/graph_felzenszwalb/image.h"
37 #include "modules/perception/lidar/detector/ncut_segmentation/common/graph_felzenszwalb/misc.h"
38 #include "modules/perception/lidar/detector/ncut_segmentation/common/graph_felzenszwalb/segment_graph.h"
39 
40 namespace apollo {
41 namespace perception {
42 namespace lidar {
43 // dissimilarity measure between pixels
44 inline float diff(Image<float> *I, int x1, int y1, int x2, int y2) {
45  return std::fabs(imRef(I, x1, y1) - imRef(I, x2, y2));
46 }
47 /*
48  * Segment an image
49  *
50  * Returns a color image representing the segmentation.
51  *
52  * im: image to segment.
53  * sigma: to smooth the image.
54  * c: constant for threshold function.
55  * min_size: minimum component size (enforced by post-processing stage).
56  * num_ccs: number of connected components in the segmentation.
57  */
58 Image<int> *segment_image(Image<float> *im, float sigma, float c, int min_size,
59  int *num_ccs) {
60  int width = im->width();
61  int height = im->height();
62  // smooth each color channel
63  Image<float> *smooth_r = smooth(im, sigma);
64  // build graph
65  edge *edges = new edge[width * height * 4];
66  int num = 0;
67  for (int y = 0; y < height; y++) {
68  for (int x = 0; x < width; x++) {
69  if (x < width - 1) {
70  edges[num].a = y * width + x;
71  edges[num].b = y * width + (x + 1);
72  edges[num].w = diff(smooth_r, x, y, x + 1, y);
73  num++;
74  }
75  if (y < height - 1) {
76  edges[num].a = y * width + x;
77  edges[num].b = (y + 1) * width + x;
78  edges[num].w = diff(smooth_r, x, y, x, y + 1);
79  num++;
80  }
81  if ((x < width - 1) && (y < height - 1)) {
82  edges[num].a = y * width + x;
83  edges[num].b = (y + 1) * width + (x + 1);
84  edges[num].w = diff(smooth_r, x, y, x + 1, y + 1);
85  num++;
86  }
87  if ((x < width - 1) && (y > 0)) {
88  edges[num].a = y * width + x;
89  edges[num].b = (y - 1) * width + (x + 1);
90  edges[num].w = diff(smooth_r, x, y, x + 1, y - 1);
91  num++;
92  }
93  }
94  }
95  delete smooth_r;
96  // segment
97  Universe *u = segment_graph(width * height, num, edges, c);
98  // post process small components
99  for (int i = 0; i < num; i++) {
100  int a = u->find(edges[i].a);
101  int b = u->find(edges[i].b);
102  if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size)))
103  u->join(a, b);
104  }
105  delete[] edges;
106  *num_ccs = u->num_sets();
107  Image<int> *output = new Image<int>(width, height);
108  for (int y = 0; y < height; y++) {
109  for (int x = 0; x < width; x++) {
110  int comp = u->find(y * width + x);
111  imRef(output, x, y) = comp;
112  }
113  }
114  delete u;
115  return output;
116 }
117 } // namespace lidar
118 } // namespace perception
119 } // namespace apollo
int height() const
Definition: image.h:55
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
int width() const
Definition: image.h:52
int find(int x)
Definition: disjoint_set.h:75
void join(int x, int y)
Definition: disjoint_set.h:84
int a
Definition: segment_graph.h:49
Definition: image.h:40
Definition: segment_graph.h:47
Image< float > * smooth(Image< float > *src, float sigma)
Definition: filter.h:71
int size(int x) const
Definition: disjoint_set.h:55
Definition: disjoint_set.h:49
Universe * segment_graph(int num_vertices, int num_edges, edge *edges, float c)
Definition: segment_graph.h:65
float w
Definition: segment_graph.h:48
int b
Definition: segment_graph.h:50
Image< int > * segment_image(Image< float > *im, float sigma, float c, int min_size, int *num_ccs)
Definition: segment_image.h:58
int num_sets() const
Definition: disjoint_set.h:56
float diff(Image< float > *I, int x1, int y1, int x2, int y2)
Definition: segment_image.h:44
#define imRef(im, x, y)
Definition: image.h:68