template<typename PointInT, typename PointOutT> void pcl_1_8::Edge<PointInT, PointOutT>::detectEdgeCanny (pcl::PointCloud<PointOutT> &output) { float tHigh = hysteresis_threshold_high_; float tLow = hysteresis_threshold_low_; const int height = input_->height; const int width = input_->width; output.resize (height * width); output.height = height; output.width = width; //pcl::console::TicToc tt; //tt.tic (); // Noise reduction using gaussian blurring pcl::PointCloud<pcl::PointXYZI>::Ptr gaussian_kernel (new pcl::PointCloud<pcl::PointXYZI>); PointCloudInPtr smoothed_cloud (new PointCloudIn); kernel_.setKernelSize (3); kernel_.setKernelSigma (1.0); kernel_.setKernelType (kernel<pcl::PointXYZI>::GAUSSIAN); kernel_.fetchKernel (*gaussian_kernel); convolution_.setKernel (*gaussian_kernel); convolution_.setInputCloud (input_); convolution_.filter (*smoothed_cloud); //PCL_ERROR ("Gaussian blur: %g\n", tt.toc ()); tt.tic (); // Edge detection usign Sobel pcl::PointCloud<PointXYZIEdge>::Ptr edges (new pcl::PointCloud<PointXYZIEdge>); setInputCloud (smoothed_cloud); detectEdgeSobel (*edges); //PCL_ERROR ("Sobel: %g\n", tt.toc ()); tt.tic (); // Edge discretization discretizeAngles (*edges); //PCL_ERROR ("Discretize: %g\n", tt.toc ()); tt.tic (); // tHigh and non-maximal supression pcl::PointCloud<pcl::PointXYZI>::Ptr maxima (new pcl::PointCloud<pcl::PointXYZI>); suppressNonMaxima (*edges, *maxima, tLow); //PCL_ERROR ("NM suppress: %g\n", tt.toc ()); tt.tic (); // 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); } } //PCL_ERROR ("Edge tracing: %g\n", tt.toc ()); // Final thresholding for (size_t i = 0; i < input_->size (); ++i) { if ((*maxima)[i].intensity == std::numeric_limits<float>::max ()) output[i].magnitude = 255; else output[i].magnitude = 0; } }
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; } } }
int main(int argc, char **argv) { // Process command line if (argc < 3) Usage(argc, argv); std::string inputFilename = argv[1]; std::string outputFilename = argv[2]; for (int i = 3; i < argc - 1; i += 2) { if (std::string(argv[i]) == std::string("-q")) QLim = atof(argv[i+1]); else if (std::string(argv[i]) == std::string("-w")) WLimF = atof(argv[i+1]); else if (std::string(argv[i]) == std::string("-f")) FilterSize = atoi(argv[i+1]); else if (std::string(argv[i]) == std::string("-m")) NonMaximaBoxSize = atoi(argv[i+1]); } // Load image image = new Ga::Image(inputFilename); // Calculate tensor Gu = new float[image->sizeX() * image->sizeY()]; Gv = new float[image->sizeX() * image->sizeY()]; Guv = new float[image->sizeX() * image->sizeY()]; computeStructureTensor(Gu, Gv, Guv); // Apply boxfilter computeBoxFilter(Gu, FilterSize); computeBoxFilter(Gv, FilterSize); computeBoxFilter(Guv, FilterSize); // Calculate interest values result = new Ga::Image(typeid(float), image->sizeX(), image->sizeY()); double wmean = 0; double normalization = 0; for (int y = 0; y < result->sizeY(); y++) { for (int x = 0; x < result->sizeX(); x++) { int index = y * image->sizeX() + x; float trace = Gu[index] + Gv[index]; float determinant = (Gu[index] * Gv[index]) - (Guv[index] * Guv[index]); float w = determinant / trace; float q = (4 * determinant) / (trace * trace); // Test for qlim and calculate wlim if (q > QLim) { result->setPixel(x, y, w); wmean += w; normalization++; } else result->setPixel(x, y, 0); } } WLim = (wmean / normalization) * WLimF; for (int y = 0; y < result->sizeY(); y++) { for (int x = 0; x < result->sizeX(); x++) { int index = y * image->sizeX() + x; float trace = Gu[index] + Gv[index]; float determinant = (Gu[index] * Gv[index]) - (Guv[index] * Guv[index]); float w = determinant / trace; // Test for wlim if (w <= WLim) result->setPixel(x, y, 0); } } // Suppress local non-maxima suppressNonMaxima(NonMaximaBoxSize); // Write result image result->write(outputFilename.c_str()); // Release memory delete image; delete result; delete[] Gu; delete[] Gv; delete[] Guv; // Return return 0; }