计算图像的拉普拉斯变换,使用方向滤波器检测边缘

来源:互联网 发布:煎饼侠 知乎 编辑:程序博客网 时间:2024/05/21 18:33
#if !defined LAPLACEZC#define LAPLACEZC#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>class LaplacianZC {  private:  // original image  cv::Mat img;  // 32-bit float image containing the Laplacian  cv::Mat laplace;  // Aperture size of the laplacian kernel  int aperture;  public:  LaplacianZC() : aperture(3) {}  // Set the aperture size of the kernel  void setAperture(int a) {  aperture= a;  }  // Get the aperture size of the kernel  int getAperture() const {  return aperture;  }  // Compute the floating point Laplacian  cv::Mat computeLaplacian(const cv::Mat& image) {  // Compute Laplacian  cv::Laplacian(image,laplace,CV_32F,aperture);  // Keep local copy of the image  // (used for zero-crossings)  img= image.clone();  return laplace;  }  // Get the Laplacian result in 8-bit image   // zero corresponds to gray level 128  // if no scale is provided, then the max value will be  // scaled to intensity 255  // You must call computeLaplacian before calling this method  cv::Mat getLaplacianImage(double scale=-1.0) {  if (scale<0) {  double lapmin, lapmax;  cv::minMaxLoc(laplace,&lapmin,&lapmax);  scale= 127/ std::max(-lapmin,lapmax);  }  cv::Mat laplaceImage;  laplace.convertTo(laplaceImage,CV_8U,scale,128);  return laplaceImage;  }  // Get a binary image of the zero-crossings  // if the product of the two adjascent pixels is  // less than threshold then this zero-crossing will be ignored  cv::Mat getZeroCrossings(float threshold=1.0) {  // Create the iterators  cv::Mat_<float>::const_iterator it= laplace.begin<float>()+laplace.step1();  cv::Mat_<float>::const_iterator itend= laplace.end<float>();  cv::Mat_<float>::const_iterator itup= laplace.begin<float>();  // Binary image initialize to white  cv::Mat binary(laplace.size(),CV_8U,cv::Scalar(255));  cv::Mat_<uchar>::iterator itout= binary.begin<uchar>()+binary.step1();  // negate the input threshold value  threshold *= -1.0;  for ( ; it!= itend; ++it, ++itup, ++itout) {  // if the product of two adjascent pixel is negative  // then there is a sign change  if (*it * *(it-1) < threshold)  *itout= 0; // horizontal zero-crossing  else if (*it * *itup < threshold)  *itout= 0; // vertical zero-crossing  }  return binary;  }  // Get a binary image of the zero-crossings  // if the product of the two adjacent pixels is  // less than threshold then this zero-crossing will be ignored  cv::Mat getZeroCrossingsWithSobel(float threshold) {  cv::Mat sx;  cv::Sobel(img,sx,CV_32F,1,0,1);  cv::Mat sy;  cv::Sobel(img,sy,CV_32F,0,1,1);  // Create the iterators  cv::Mat_<float>::const_iterator it= laplace.begin<float>()+laplace.step1();  cv::Mat_<float>::const_iterator itend= laplace.end<float>();  cv::Mat_<float>::const_iterator itup= laplace.begin<float>();  cv::Mat_<float>::const_iterator itx= sx.begin<float>()+sx.step1();  cv::Mat_<float>::const_iterator ity= sy.begin<float>()+sy.step1();  // Binary image initialize to white  cv::Mat binary(laplace.size(),CV_8U,cv::Scalar(255));  cv::Mat_<uchar>::iterator itout= binary.begin<uchar>()+binary.step1();  for ( ; it!= itend; ++it, ++itup, ++itout, ++itx, ++ity) {  // if the product of two adjacent pixel is negative  // then there is a sign change  if (*it * *(it-1) < 0.0 && fabs(*ity) > threshold)  *itout= 0; // horizontal zero-crossing  else if (*it * *itup < 0.0 && fabs(*ity) > threshold)  *itout= 0; // vertical zero-crossing  }  return binary;  }};#endif#include <iostream>#include <iomanip>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include "laplacianZC.h"int main(){// Read input imagecv::Mat image= cv::imread("d:/test/opencv/boldt.jpg",0);if (!image.data)return 0;     // Display the imagecv::namedWindow("Original Image");cv::imshow("Original Image",image);// Compute Sobel X derivativecv::Mat sobelX;cv::Sobel(image,sobelX,CV_8U,1,0,3,0.4,128);    // Display the imagecv::namedWindow("Sobel X Image");cv::imshow("Sobel X Image",sobelX);// Compute Sobel Y derivativecv::Mat sobelY;cv::Sobel(image,sobelY,CV_8U,0,1,3,0.4,128);    // Display the imagecv::namedWindow("Sobel Y Image");cv::imshow("Sobel Y Image",sobelY);// Compute norm of Sobelcv::Sobel(image,sobelX,CV_16S,1,0);cv::Sobel(image,sobelY,CV_16S,0,1);cv::Mat sobel;//compute the L1 normsobel= abs(sobelX)+abs(sobelY);double sobmin, sobmax;cv::minMaxLoc(sobel,&sobmin,&sobmax);std::cout << "sobel value range: " << sobmin << "  " << sobmax << std::endl;// Print window pixel valuesfor (int i=0; i<12; i++) {for (int j=0; j<12; j++)std::cout << std::setw(5) << static_cast<int>(sobel.at<short>(i+135,j+362)) << " ";std::cout << std::endl;}std::cout << std::endl;std::cout << std::endl;std::cout << std::endl;// Conversion to 8-bit image// sobelImage = -alpha*sobel + 255cv::Mat sobelImage;sobel.convertTo(sobelImage,CV_8U,-255./sobmax,255);    // Display the imagecv::namedWindow("Sobel Image");cv::imshow("Sobel Image",sobelImage);// Apply threshold to Sobel norm (low threshold value)cv::Mat sobelThresholded;cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY);    // Display the imagecv::namedWindow("Binary Sobel Image (low)");cv::imshow("Binary Sobel Image (low)",sobelThresholded);// Apply threshold to Sobel norm (high threshold value)cv::threshold(sobelImage, sobelThresholded, 190, 255, cv::THRESH_BINARY);    // Display the imagecv::namedWindow("Binary Sobel Image (high)");cv::imshow("Binary Sobel Image (high)",sobelThresholded);// Compute Laplacian 3x3cv::Mat laplace;cv::Laplacian(image,laplace,CV_8U,1,1,128);    // Display the imagecv::namedWindow("Laplacian Image");cv::imshow("Laplacian Image",laplace);// Print window pixel valuesfor (int i=0; i<12; i++) {for (int j=0; j<12; j++)std::cout << std::setw(5) << static_cast<int>(laplace.at<uchar>(i+135,j+362))-128 << " ";std::cout << std::endl;}std::cout << std::endl;std::cout << std::endl;std::cout << std::endl;// Compute Laplacian 7x7cv::Laplacian(image,laplace,CV_8U,7,0.01,128);    // Display the image cv::namedWindow("Laplacian Image");cv::imshow("Laplacian Image",laplace);// Print window pixel valuesfor (int i=0; i<12; i++) {for (int j=0; j<12; j++)std::cout << std::setw(5) << static_cast<int>(laplace.at<uchar>(i+135,j+362))-128 << " ";std::cout << std::endl;}    // Extract small windowcv::Mat window(image,cv::Rect(362,135,12,12));cv::namedWindow("Image window");cv::imshow("Image window",window);cv::imwrite("window.bmp",window);// Compute Laplacian using LaplacianZC classLaplacianZC laplacian;laplacian.setAperture(7);cv::Mat flap= laplacian.computeLaplacian(image);double lapmin, lapmax;cv::minMaxLoc(flap,&lapmin,&lapmax);std::cout << "Laplacian value range=[" << lapmin << "," << lapmax << "]\n";laplace= laplacian.getLaplacianImage();cv::namedWindow("Laplacian Image (7x7)");cv::imshow("Laplacian Image (7x7)",laplace);// Print Laplacian valuesstd::cout << std::endl;for (int i=0; i<12; i++) {for (int j=0; j<12; j++)std::cout << std::setw(5) << static_cast<int>(flap.at<float>(i+135,j+362)/100) << " ";std::cout << std::endl;}std::cout << std::endl;// Compute and display the zero-crossing pointscv::Mat zeros;zeros= laplacian.getZeroCrossings(lapmax);cv::namedWindow("Zero-crossings");cv::imshow("Zero-crossings",zeros);// Compute and display the zero-crossing points (Sobel version)zeros= laplacian.getZeroCrossings();zeros= laplacian.getZeroCrossingsWithSobel(50);cv::namedWindow("Zero-crossings (2)");cv::imshow("Zero-crossings (2)",zeros);// Print window pixel valuesfor (int i=0; i<12; i++) {for (int j=0; j<12; j++)std::cout << std::setw(2) << static_cast<int>(zeros.at<uchar>(i+135,j+362)) << " ";std::cout << std::endl;}    // Display the image with windowcv::rectangle(image,cv::Point(362,135),cv::Point(374,147),cv::Scalar(255,255,255));cv::namedWindow("Original Image with window");cv::imshow("Original Image with window",image);cv::waitKey();return 0;}

1 0
原创粉丝点击