38 #ifndef PCL_2D_EDGE_IMPL_HPP 39 #define PCL_2D_EDGE_IMPL_HPP 41 #include <pcl/2d/convolution.h> 42 #include <pcl/common/common_headers.h> 43 #include <pcl/console/time.h> 46 template <
typename Po
intInT,
typename Po
intOutT>
void 52 convolution_.setInputCloud (input_);
56 kernel_.fetchKernel (*kernel_x);
57 convolution_.setKernel (*kernel_x);
58 convolution_.filter (*magnitude_x);
64 kernel_.fetchKernel (*kernel_y);
65 convolution_.setKernel (*kernel_y);
66 convolution_.filter (*magnitude_y);
69 const int height = input_->height;
70 const int width = input_->width;
72 output.
resize (height * width);
76 for (
size_t i = 0; i < output.
size (); ++i)
78 output[i].magnitude_x = (*magnitude_x)[i].intensity;
79 output[i].magnitude_y = (*magnitude_y)[i].intensity;
81 std::sqrt ((*magnitude_x)[i].intensity * (*magnitude_x)[i].intensity +
82 (*magnitude_y)[i].intensity * (*magnitude_y)[i].intensity);
84 atan2f ((*magnitude_y)[i].intensity, (*magnitude_x)[i].intensity);
90 template <
typename Po
intInT,
typename Po
intOutT>
void 96 convolution_.setInputCloud (input_x.
makeShared());
100 kernel_.fetchKernel (*kernel_x);
101 convolution_.setKernel (*kernel_x);
102 convolution_.filter (*magnitude_x);
104 convolution_.setInputCloud (input_y.
makeShared());
108 kernel_.fetchKernel (*kernel_y);
109 convolution_.setKernel (*kernel_y);
110 convolution_.filter (*magnitude_y);
112 const int height = input_x.
height;
113 const int width = input_x.
width;
115 output.
resize (height * width);
117 output.
width = width;
119 for (
size_t i = 0; i < output.
size (); ++i)
121 output[i].magnitude_x = (*magnitude_x)[i].intensity;
122 output[i].magnitude_y = (*magnitude_y)[i].intensity;
123 output[i].magnitude =
124 std::sqrt ((*magnitude_x)[i].intensity * (*magnitude_x)[i].intensity +
125 (*magnitude_y)[i].intensity * (*magnitude_y)[i].intensity);
126 output[i].direction =
127 atan2f ((*magnitude_y)[i].intensity, (*magnitude_x)[i].intensity);
132 template <
typename Po
intInT,
typename Po
intOutT>
void 135 convolution_.setInputCloud (input_);
140 kernel_.fetchKernel (*kernel_x);
141 convolution_.setKernel (*kernel_x);
142 convolution_.filter (*magnitude_x);
147 kernel_.fetchKernel (*kernel_y);
148 convolution_.setKernel (*kernel_y);
149 convolution_.filter (*magnitude_y);
151 const int height = input_->height;
152 const int width = input_->width;
154 output.
resize (height * width);
156 output.
width = width;
158 for (
size_t i = 0; i < output.
size (); ++i)
160 output[i].magnitude_x = (*magnitude_x)[i].intensity;
161 output[i].magnitude_y = (*magnitude_y)[i].intensity;
162 output[i].magnitude =
163 std::sqrt ((*magnitude_x)[i].intensity * (*magnitude_x)[i].intensity +
164 (*magnitude_y)[i].intensity * (*magnitude_y)[i].intensity);
165 output[i].direction =
166 atan2f ((*magnitude_y)[i].intensity, (*magnitude_x)[i].intensity);
171 template <
typename Po
intInT,
typename Po
intOutT>
void 174 convolution_.setInputCloud (input_);
179 kernel_.fetchKernel (*kernel_x);
180 convolution_.setKernel (*kernel_x);
181 convolution_.filter (*magnitude_x);
186 kernel_.fetchKernel (*kernel_y);
187 convolution_.setKernel (*kernel_y);
188 convolution_.filter (*magnitude_y);
190 const int height = input_->height;
191 const int width = input_->width;
193 output.
resize (height * width);
195 output.
width = width;
197 for (
size_t i = 0; i < output.
size (); ++i)
199 output[i].magnitude_x = (*magnitude_x)[i].intensity;
200 output[i].magnitude_y = (*magnitude_y)[i].intensity;
201 output[i].magnitude =
202 std::sqrt ((*magnitude_x)[i].intensity * (*magnitude_x)[i].intensity +
203 (*magnitude_y)[i].intensity * (*magnitude_y)[i].intensity);
204 output[i].direction =
205 atan2f ((*magnitude_y)[i].intensity, (*magnitude_x)[i].intensity);
210 template<
typename Po
intInT,
typename Po
intOutT>
void 212 int rowOffset,
int colOffset,
int row,
int col,
215 int newRow = row + rowOffset;
216 int newCol = col + colOffset;
219 if (newRow > 0 && newRow < static_cast<int> (maxima.
height) && newCol > 0 && newCol < static_cast<int> (maxima.
width))
224 pt.
intensity = std::numeric_limits<float>::max ();
225 cannyTraceEdge ( 1, 0, newRow, newCol, maxima);
226 cannyTraceEdge (-1, 0, newRow, newCol, maxima);
227 cannyTraceEdge ( 1, 1, newRow, newCol, maxima);
228 cannyTraceEdge (-1, -1, newRow, newCol, maxima);
229 cannyTraceEdge ( 0, -1, newRow, newCol, maxima);
230 cannyTraceEdge ( 0, 1, newRow, newCol, maxima);
231 cannyTraceEdge (-1, 1, newRow, newCol, maxima);
232 cannyTraceEdge ( 1, -1, newRow, newCol, maxima);
237 template <
typename Po
intInT,
typename Po
intOutT>
void 240 const int height = thet.
height;
241 const int width = thet.
width;
243 for (
int i = 0; i < height; i++)
245 for (
int j = 0; j < width; j++)
248 if (((angle <= 22.5) && (angle >= -22.5)) || (angle >= 157.5) || (angle <= -157.5))
249 thet (j, i).direction = 0;
251 if (((angle > 22.5) && (angle < 67.5)) || ((angle < -112.5) && (angle > -157.5)))
252 thet (j, i).direction = 45;
254 if (((angle >= 67.5) && (angle <= 112.5)) || ((angle <= -67.5) && (angle >= -112.5)))
255 thet (j, i).direction = 90;
257 if (((angle > 112.5) && (angle < 157.5)) || ((angle < -22.5) && (angle > -67.5)))
258 thet (j, i).direction = 135;
264 template <
typename Po
intInT,
typename Po
intOutT>
void 269 const int height = edges.
height;
270 const int width = edges.
width;
273 maxima.
width = width;
274 maxima.
resize (height * width);
276 for (
size_t i = 0; i < maxima.
size (); ++i)
277 maxima[i].intensity = 0.0f;
280 for (
int i = 1; i < height - 1; i++)
282 for (
int j = 1; j < width - 1; j++)
284 const PointXYZIEdge &ptedge = edges (j, i);
285 PointXYZI &ptmax = maxima (j, i);
287 if (ptedge.magnitude < tLow)
292 switch (
int (ptedge.direction))
296 if (ptedge.magnitude >= edges (j - 1, i).magnitude &&
297 ptedge.magnitude >= edges (j + 1, i).magnitude)
298 ptmax.intensity = ptedge.magnitude;
303 if (ptedge.magnitude >= edges (j - 1, i - 1).magnitude &&
304 ptedge.magnitude >= edges (j + 1, i + 1).magnitude)
305 ptmax.intensity = ptedge.magnitude;
310 if (ptedge.magnitude >= edges (j, i - 1).magnitude &&
311 ptedge.magnitude >= edges (j, i + 1).magnitude)
312 ptmax.intensity = ptedge.magnitude;
317 if (ptedge.magnitude >= edges (j + 1, i - 1).magnitude &&
318 ptedge.magnitude >= edges (j - 1, i + 1).magnitude)
319 ptmax.intensity = ptedge.magnitude;
328 template<
typename Po
intInT,
typename Po
intOutT>
void 331 float tHigh = hysteresis_threshold_high_;
332 float tLow = hysteresis_threshold_low_;
333 const int height = input_->height;
334 const int width = input_->width;
336 output.
resize (height * width);
338 output.
width = width;
346 kernel_.setKernelSize (3);
347 kernel_.setKernelSigma (1.0);
349 kernel_.fetchKernel (*gaussian_kernel);
350 convolution_.setKernel (*gaussian_kernel);
351 convolution_.setInputCloud (input_);
352 convolution_.filter (*smoothed_cloud);
357 setInputCloud (smoothed_cloud);
358 detectEdgeSobel (*edges);
362 discretizeAngles (*edges);
367 suppressNonMaxima (*edges, *maxima, tLow);
371 for (
int i = 0; i < height; i++)
373 for (
int j = 0; j < width; j++)
375 if ((*maxima)(j, i).intensity < tHigh || (*maxima)(j, i).intensity == std::numeric_limits<float>::max ())
378 (*maxima)(j, i).intensity = std::numeric_limits<float>::max ();
379 cannyTraceEdge ( 1, 0, i, j, *maxima);
380 cannyTraceEdge (-1, 0, i, j, *maxima);
381 cannyTraceEdge ( 1, 1, i, j, *maxima);
382 cannyTraceEdge (-1, -1, i, j, *maxima);
383 cannyTraceEdge ( 0, -1, i, j, *maxima);
384 cannyTraceEdge ( 0, 1, i, j, *maxima);
385 cannyTraceEdge (-1, 1, i, j, *maxima);
386 cannyTraceEdge ( 1, -1, i, j, *maxima);
392 for (
size_t i = 0; i < input_->size (); ++i)
394 if ((*maxima)[i].intensity == std::numeric_limits<float>::max ())
395 output[i].magnitude = 255;
397 output[i].magnitude = 0;
402 template <
typename Po
intInT,
typename Po
intOutT>
void 408 float tHigh = hysteresis_threshold_high_;
409 float tLow = hysteresis_threshold_low_;
410 const int height = input_x.
height;
411 const int width = input_x.
width;
413 output.
resize (height * width);
415 output.
width = width;
419 kernel_.setKernelSize (3);
420 kernel_.setKernelSigma (1.0);
422 kernel_.fetchKernel (*gaussian_kernel);
423 convolution_.setKernel (*gaussian_kernel);
426 convolution_.setInputCloud (input_x.
makeShared());
427 convolution_.filter (smoothed_cloud_x);
430 convolution_.setInputCloud (input_y.
makeShared());
431 convolution_.filter (smoothed_cloud_y);
436 sobelMagnitudeDirection (smoothed_cloud_x, smoothed_cloud_y, *edges.get ());
439 discretizeAngles (*edges);
442 suppressNonMaxima (*edges, *maxima, tLow);
445 for (
int i = 0; i < height; i++)
447 for (
int j = 0; j < width; j++)
449 if ((*maxima)(j, i).intensity < tHigh || (*maxima)(j, i).intensity == std::numeric_limits<float>::max ())
452 (*maxima)(j, i).intensity = std::numeric_limits<float>::max ();
453 cannyTraceEdge ( 1, 0, i, j, *maxima);
454 cannyTraceEdge (-1, 0, i, j, *maxima);
455 cannyTraceEdge ( 1, 1, i, j, *maxima);
456 cannyTraceEdge (-1, -1, i, j, *maxima);
457 cannyTraceEdge ( 0, -1, i, j, *maxima);
458 cannyTraceEdge ( 0, 1, i, j, *maxima);
459 cannyTraceEdge (-1, 1, i, j, *maxima);
460 cannyTraceEdge ( 1, -1, i, j, *maxima);
465 for (
int i = 0; i < height; i++)
467 for (
int j = 0; j < width; j++)
469 if ((*maxima)(j, i).intensity == std::numeric_limits<float>::max ())
470 output (j, i).magnitude = 255;
472 output (j, i).magnitude = 0;
478 template<
typename Po
intInT,
typename Po
intOutT>
void 480 const float kernel_sigma,
const float kernel_size,
483 convolution_.setInputCloud (input_);
487 kernel_.setKernelSigma (kernel_sigma);
488 kernel_.setKernelSize (kernel_size);
489 kernel_.fetchKernel (*log_kernel);
490 convolution_.setKernel (*log_kernel);
491 convolution_.filter (output);
float rad2deg(float alpha)
Convert an angle from radians to degrees.
uint32_t height
The point cloud height (if organized as an image-structure).
boost::shared_ptr< PointCloud< PointT > > Ptr
void sobelMagnitudeDirection(const pcl::PointCloud< PointInT > &input_x, const pcl::PointCloud< PointInT > &input_y, pcl::PointCloud< PointOutT > &output)
uint32_t width
The point cloud width (if organized as an image-structure).
void detectEdgePrewitt(pcl::PointCloud< PointOutT > &output)
Uses the Prewitt kernel for edge detection.
void canny(const pcl::PointCloud< PointInT > &input_x, const pcl::PointCloud< PointInT > &input_y, pcl::PointCloud< PointOutT > &output)
Perform Canny edge detection with two separated input images for horizontal and vertical derivatives...
PointCloud represents the base class in PCL for storing collections of 3D points. ...
void detectEdgeSobel(pcl::PointCloud< PointOutT > &output)
Uses the Sobel kernel for edge detection.
void detectEdgeLoG(const float kernel_sigma, const float kernel_size, pcl::PointCloud< PointOutT > &output)
Uses the LoG kernel for edge detection.
Ptr makeShared() const
Copy the cloud to the heap and return a smart pointer Note that deep copy is performed, so avoid using this function on non-empty clouds.
void resize(size_t n)
Resize the cloud.
void detectEdgeCanny(pcl::PointCloud< PointOutT > &output)
All edges of magnitude above t_high are always classified as edges.
void detectEdgeRoberts(pcl::PointCloud< PointOutT > &output)
Uses the Roberts kernel for edge detection.