PICCANTE  0.4
The hottest HDR imaging library!
canny_edge_detector.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_FEATURES_MATCHING_CANNY_EDGE_DETECTOR_HPP
19 #define PIC_FEATURES_MATCHING_CANNY_EDGE_DETECTOR_HPP
20 
21 #include "../util/vec.hpp"
22 #include "../util/std_util.hpp"
23 #include "../image.hpp"
24 
25 #include "../filtering/filter_luminance.hpp"
26 #include "../filtering/filter_gaussian_2d.hpp"
27 #include "../filtering/filter_gradient.hpp"
28 
29 namespace pic {
30 
35 {
36 protected:
37  bool bLum;
39 
41 
45  void release()
46  {
47  if(bLum) {
48  lum = delete_s(lum);
49  }
50 
51  bLum = false;
52  }
53 
54 public:
59  {
60  lum = NULL;
61  bLum = false;
62 
63  update();
64  }
65 
67  {
68  release();
69  }
70 
77  void update(float sigma = 1.4f, float threshold_1 = 0.05f, float threshold_2 = 0.3f)
78  {
79  this->sigma = sigma > 0.0f ? sigma : 1.4f;
80  this->threshold_1 = threshold_1 > 0.0f ? threshold_1 : 0.05f;
81  this->threshold_2 = threshold_2 > 0.0f ? threshold_1 : 0.3f;
82 
83  if(threshold_2 < threshold_1) {
84  float tmp = threshold_1;
86  threshold_2 = tmp;
87  }
88  }
89 
96  Image *execute(Image *img, Image *imgOut)
97  {
98  if(img == NULL) {
99  return imgOut;
100  }
101 
102  if(img->channels == 1) {
103  release();
104  lum = img;
105  } else {
106  bLum = true;
108  }
109 
110  //filter the image
111  FilterGaussian2D flt(sigma);
112  Image *lum_flt = flt.Process(Single(lum), NULL);
113 
114  FilterGradient fltGrad(0, G_SOBEL);
115  Image *grad = fltGrad.Process(Single(lum_flt), NULL);
116 
117  //non-maximum suppression
118  if(imgOut == NULL) {
119  imgOut = lum->allocateSimilarOne();
120  }
121 
122  imgOut->setZero();
123 
124  int dx0[] = {1, 1, 0, -1, 1};
125  int dy0[] = {0, 1, 1, 1, 0};
126 
127  int dx1[] = {-1, -1, 0, 1, -1};
128  int dy1[] = { 0, -1, -1, -1, 0};
129 
130  for(int i = 0; i < grad->height; i++) {
131  for(int j = 0; j < grad->width; j++) {
132 
133  float *tmp_grad = (*grad)(j, i);
134 
135  float angle = atan2(tmp_grad[1], tmp_grad[0]);
136 
137  angle = Rad2Deg(angle < 0.0f ? C_PI + angle : angle);
138  int k = int(lround(angle / 45.0f));
139 
140  bool bMax = (tmp_grad[2] > (*grad)(j + dx0[k], i + dy0[k])[2]) &&
141  (tmp_grad[2] > (*grad)(j + dx1[k], i + dy1[k])[2]);
142 
143  /*
144  bool bMax = false;
145 
146  if(((angle >= 0.0f) && (angle < 22.5f)) ||
147  ((angle >= 157.5f))) {
148  bMax = (tmp_grad[2] > (*grad)(j + 1, i)[2]) &&
149  (tmp_grad[2] > (*grad)(j - 1, i)[2]);
150  }
151 
152  if((angle >= 22.5f) && (angle < 67.5f)) {
153  bMax = (tmp_grad[2] > (*grad)(j + 1, i + 1)[2]) &&
154  (tmp_grad[2] > (*grad)(j - 1, i - 1)[2]);
155  }
156 
157  if((angle >= 67.5f) && (angle < 112.5f)) {
158  bMax = (tmp_grad[2] > (*grad)(j, i + 1)[2]) &&
159  (tmp_grad[2] > (*grad)(j, i - 1)[2]);
160  }
161 
162  if((angle >= 112.5f) && (angle < 157.5f)) {
163  bMax = (tmp_grad[2] > (*grad)(j - 1, i + 1)[2]) &&
164  (tmp_grad[2] > (*grad)(j + 1, i - 1)[2]);
165  }*/
166 
167  float *imgOut_ji = (*imgOut)(j, i);
168 
169  imgOut_ji[0] = bMax ? tmp_grad[2] : 0.0f;
170  }
171  }
172 
173  //double thresholding
174  for(int i = 0; i < imgOut->height; i++) {
175  for(int j = 0; j < imgOut->width; j++) {
176  float *imgOut_ji = (*imgOut)(j, i);
177 
178  if(imgOut_ji[0] > threshold_2) {
179  imgOut_ji[0] = 1.0f; //strong edge
180  } else {
181  //0.5f --> weak edge
182  //0.0f --> no edge
183  imgOut_ji[0] = imgOut_ji[0] > threshold_1 ? 0.5f : 0.0f;
184  }
185  }
186  }
187 
188  //remove false edges: a weak edge is a strong one
189  //if it is connected to a strong edge
190  int x[] = {1, 1, 0, -1, -1, -1, 0, 1};
191  int y[] = {0, 1, 1, 1, 0, -1, -1, -1};
192 
193  for(int i = 0; i < imgOut->height; i++) {
194  for(int j = 0; j < imgOut->width; j++) {
195  float *imgOut_ji = (*imgOut)(j, i);
196 
197  if((imgOut_ji[0] > 0.4f) && (imgOut_ji[0] < 0.6f)) {
198  bool bRemove = true;
199 
200  for(int k = 0; k < 8; k++) {
201  float *imgOut_ji_xy = (*imgOut)(j + x[k], i + y[k]);
202 
203  if(imgOut_ji_xy[0] > 0.9f) {
204  bRemove = false;
205  break;
206  }
207  }
208 
209  imgOut_ji[0] = bRemove ? 0.0f : 1.0f;
210  }
211  }
212  }
213 
214  delete lum_flt;
215  delete grad;
216 
217  return imgOut;
218  }
219 };
220 
221 } // end namespace pic
222 
223 #endif /* PIC_FEATURES_MATCHING_CANNY_EDGE_DETECTOR_HPP */
224 
void update(float sigma=1.4f, float threshold_1=0.05f, float threshold_2=0.3f)
update
Definition: canny_edge_detector.hpp:77
Definition: filter_luminance.hpp:28
bool bLum
Definition: canny_edge_detector.hpp:37
void setZero()
setZero sets data to 0.0f.
int channels
Definition: image.hpp:80
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
PIC_INLINE long lround(double x)
lround rounds double numbers properly.
Definition: math.hpp:229
~CannyEdgeDetector()
Definition: canny_edge_detector.hpp:66
void release()
release frees allocated memory for this class.
Definition: canny_edge_detector.hpp:45
const float C_PI
Definition: math.hpp:50
float threshold_1
Definition: canny_edge_detector.hpp:40
virtual Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter.hpp:390
static Image * execute(Image *imgIn, Image *imgOut, LUMINANCE_TYPE type=LT_CIE_LUMINANCE)
execute
Definition: filter_luminance.hpp:166
Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter_npasses.hpp:310
The Image class stores an image as buffer of float.
Definition: image.hpp:60
float sigma
Definition: canny_edge_detector.hpp:40
Image * allocateSimilarOne()
allocateSimilarOne creates an Image with similar size of the calling instance.
Image * execute(Image *img, Image *imgOut)
execute executes Canny edge detector on img and ouputs imgEdges as results.
Definition: canny_edge_detector.hpp:96
PIC_INLINE float Rad2Deg(float rad)
Rad2Deg converts angles expressed in radians into angles expressed in degrees.
Definition: math.hpp:292
Image * lum
Definition: canny_edge_detector.hpp:38
PIC_INLINE ImageVec Single(Image *img)
Single creates an std::vector which contains img; this is for filters input.
Definition: image_vec.hpp:36
Definition: bilateral_separation.hpp:25
The FilterGradient class.
Definition: filter_gradient.hpp:30
The CannyEdgeDetector class.
Definition: canny_edge_detector.hpp:34
The FilterGaussian2D class.
Definition: filter_gaussian_2d.hpp:31
CannyEdgeDetector()
CannyEdgeDetector.
Definition: canny_edge_detector.hpp:58
float threshold_2
Definition: canny_edge_detector.hpp:40
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
Definition: filter_gradient.hpp:25