void pcl::pcl_2d::edge::canny (ImageType &output, ImageType &input) { float tHigh = 50; float tLow = 20; const int height = input.size(); const int width = input[0].size(); /*noise reduction using gaussian blurring*/ ImageType gaussian_kernel; conv_2d->gaussianKernel (5, 1.4, gaussian_kernel); conv_2d->convolve (output, gaussian_kernel, input); /*edge detection usign Sobel*/ ImageType G; ImageType thet; sobelMagnitudeDirection (G, thet, input); /*edge discretization*/ float angle; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { angle = (thet[i][j] / 3.14f) * 180; if (((angle < 22.5) && (angle > -22.5)) || (angle > 157.5) || (angle < -157.5)) thet[i][j] = 0; else if (((angle > 22.5) && (angle < 67.5)) || ((angle < -112.5) && (angle > -157.5))) thet[i][j] = 45; else if (((angle > 67.5) && (angle < 112.5)) || ((angle < -67.5) && (angle > -112.5))) thet[i][j] = 90; else if (((angle > 112.5) && (angle < 157.5)) || ((angle < -22.5) && (angle > -67.5))) thet[i][j] = 135; } } float max; /*tHigh and non-maximal supression*/ for (int i = 1; i < height - 1; i++) { for (int j = 1; j < width - 1; j++) { if (G[i][j] < tHigh) continue; max = G[i][j]; switch ((int)thet[i][j]) { case 0: if(G[i][j] < G[i][j-1] || G[i][j] < G[i][j+1]) G[i][j] = 0; break; case 45: if(G[i][j] < G[i-1][j+1] || G[i][j] < G[i+1][j-1]) G[i][j] = 0; break; case 90: if(G[i][j] < G[i-1][j] || G[i][j] < G[i+1][j]) G[i][j] = 0; break; case 135: if(G[i][j] < G[i-1][j-1] || G[i][j] < G[i+1][j+1]) G[i][j] = 0; break; } } } /*edge tracing*/ for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (G[i][j] < tHigh) continue; switch ((int)thet[i][j]) { case 0: cannyTraceEdge (1, 0, i, j, 0, tLow, tHigh, G, thet); cannyTraceEdge (-1, 0, i, j, 0, tLow, tHigh, G, thet); break; case 45: cannyTraceEdge (1, 1, i, j, 45, tLow, tHigh, G, thet); cannyTraceEdge (-1, -1, i, j, 45, tLow, tHigh, G, thet); break; case 90: cannyTraceEdge (0, -1, i, j, 90, tLow, tHigh, G, thet); cannyTraceEdge (0, 1, i, j, 90, tLow, tHigh, G, thet); break; case 135: cannyTraceEdge (-1, 1, i, j, 135, tLow, tHigh, G, thet); cannyTraceEdge (1, -1, i, j, 135, tLow, tHigh, G, thet); break; } } } /*final thresholding*/ output.resize (height); for (int i = 0; i < height; i++) { output[i].resize (width); for (int j = 0; j < width; j++) { if (G[i][j] < tHigh) output[i][j] = 0; else output[i][j] = 255; } } }
template <typename PointInT, typename PointOutT> void pcl_1_8::Edge<PointInT, PointOutT>::canny ( const pcl::PointCloud<PointInT> &input_x, const pcl::PointCloud<PointInT> &input_y, pcl::PointCloud<PointOutT> &output) { float tHigh = hysteresis_threshold_high_; float tLow = hysteresis_threshold_low_; const int height = input_x.height; const int width = input_x.width; output.resize (height * width); output.height = height; output.width = width; // Noise reduction using gaussian blurring pcl::PointCloud<pcl::PointXYZI>::Ptr gaussian_kernel (new pcl::PointCloud<pcl::PointXYZI>); kernel_.setKernelSize (3); kernel_.setKernelSigma (1.0); kernel_.setKernelType (kernel<pcl::PointXYZI>::GAUSSIAN); kernel_.fetchKernel (*gaussian_kernel); convolution_.setKernel (*gaussian_kernel); PointCloudIn smoothed_cloud_x; convolution_.setInputCloud (input_x.makeShared()); convolution_.filter (smoothed_cloud_x); PointCloudIn smoothed_cloud_y; convolution_.setInputCloud (input_y.makeShared()); convolution_.filter (smoothed_cloud_y); // Edge detection usign Sobel pcl::PointCloud<PointXYZIEdge>::Ptr edges (new pcl::PointCloud<PointXYZIEdge>); sobelMagnitudeDirection (smoothed_cloud_x, smoothed_cloud_y, *edges.get ()); // Edge discretization discretizeAngles (*edges); pcl::PointCloud<pcl::PointXYZI>::Ptr maxima (new pcl::PointCloud<pcl::PointXYZI>); suppressNonMaxima (*edges, *maxima, tLow); // Edge tracing for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if ((*maxima)(j, i).intensity < tHigh || (*maxima)(j, i).intensity == std::numeric_limits<float>::max ()) continue; (*maxima)(j, i).intensity = std::numeric_limits<float>::max (); cannyTraceEdge ( 1, 0, i, j, *maxima); cannyTraceEdge (-1, 0, i, j, *maxima); cannyTraceEdge ( 1, 1, i, j, *maxima); cannyTraceEdge (-1, -1, i, j, *maxima); cannyTraceEdge ( 0, -1, i, j, *maxima); cannyTraceEdge ( 0, 1, i, j, *maxima); cannyTraceEdge (-1, 1, i, j, *maxima); cannyTraceEdge ( 1, -1, i, j, *maxima); } } // Final thresholding for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if ((*maxima)(j, i).intensity == std::numeric_limits<float>::max ()) output (j, i).magnitude = 255; else output (j, i).magnitude = 0; } } }