首页 > 代码库 > 形态学滤波(3):使用形态学滤波对图像进行边缘及角点检测.

形态学滤波(3):使用形态学滤波对图像进行边缘及角点检测.

  1 #include<opencv2/opencv.hpp>
  2 #include<iostream>
  3 
  4 using namespace std;
  5 using namespace cv;
  6 
  7 //首先定义MorphoFeatures类,我们将使用它来检测图像特征
  8 class MorphoFeatures {
  9 private:
 10     int threShold;  //用于生成二值图像的阈值
 11     Mat cross;      //角点检测中用到的结构元素
 12     Mat diamond;
 13     Mat square;
 14     Mat x; 
 15 public:
 16     /*
 17         使用形态学检测角点,OpenCV没有直接实现它。这是一个很好的使用非方形结构元素的例子。
 18         事实上,它需要定义四种不同的结构元素,包括方形、菱形、十字形以及X形,这都是在构造
 19         函数中完成的(简单起见,所有元素的尺寸都固定为5*5)
 20     */
 21     MorphoFeatures() :threShold(-1), cross(5, 5, CV_8U, Scalar(0)),
 22         diamond(5, 5, CV_8U, Scalar(0)),
 23         square(5, 5, CV_8U, Scalar(0)),
 24         x(5, 5, CV_8U, Scalar(0)) {
 25         //创建十字形元素
 26         for (int i = 0; i < 5; i++) {
 27             cross.at<uchar>(2, i) = 1;
 28             cross.at<uchar>(i, 2) = 1;
 29         }
 30 
 31         //创建菱形元素
 32         diamond.at<uchar>(0, 0) = 0;
 33         diamond.at<uchar>(0, 1) = 0;
 34         diamond.at<uchar>(1, 0) = 0;
 35         diamond.at<uchar>(4, 4) = 0;
 36         diamond.at<uchar>(3, 4) = 0;
 37         diamond.at<uchar>(4, 3) = 0;
 38         diamond.at<uchar>(4, 0) = 0;
 39         diamond.at<uchar>(4, 1) = 0;
 40         diamond.at<uchar>(3, 0) = 0;
 41         diamond.at<uchar>(0, 4) = 0;
 42         diamond.at<uchar>(0, 3) = 0;
 43         diamond.at<uchar>(1, 4) = 0;
 44 
 45         //创建X形元素
 46         for (int i = 0; i < 5; i++) {
 47             x.at<uchar>(i, i) = 1;
 48             x.at<uchar>(4-i, i) = 1;
 49         }
 50     }
 51 
 52     //在检测角点特征的过程中,需要接连使用这些结构元素以得到最终的角点映射图
 53     Mat getCorners(const Mat &image) {
 54         Mat result;
 55         //十字形膨胀
 56         dilate(image, result, cross);
 57         //菱形腐蚀
 58         erode(result, result, diamond);
 59 
 60         Mat result2;
 61 
 62         //X形膨胀
 63         dilate(image, result2, x);
 64         //方形腐蚀
 65         erode(result2, result2, square);
 66 
 67         //通过对两张图像做差值得到角点图像
 68         absdiff(result2, result, result);
 69         //阈值化以得到二值图像
 70         applyThreshold(result);
 71 
 72         return result;
 73     }
 74     //为了更好的可视化检测的结果,使用下述方法在二值图像中的每个检测点上绘制一个园
 75     void drawOnImage(const Mat &binary, Mat &image) {
 76         Mat_<uchar>::const_iterator it = binary.begin<uchar>();
 77         Mat_<uchar>::const_iterator itend = binary.end<uchar>();
 78 
 79         //遍历每个像素
 80         for (int i = 0; it != itend; ++it, ++i) {
 81             if (!*it)
 82                 circle(image, Point(i%image.step, i / image.step), 5, Scalar(255, 0, 0));
 83         }
 84     }
 85     void setThreshold(int t) {
 86         threShold = t;
 87     }
 88     Mat getEdges(const Mat & image) {
 89         //得到梯度图
 90         Mat result;
 91         morphologyEx(image, result, MORPH_GRADIENT, Mat());
 92     
 93         //阈值化得到二值图像
 94         applyThreshold(result);
 95         return result;
 96     }
 97 
 98     void applyThreshold(Mat &result) {
 99         if (threShold > 0)
100             threshold(result, result, threShold, 255, THRESH_BINARY);
101     }
102 };
103 
104 
105 int main()
106 {
107     Mat    image = imread("C:\\Users\\Administrator\\Pictures\\Camera Roll\\07.jpg");
108 
109     //创建形态学特征实例
110     MorphoFeatures morpho;
111     //morpho.setThreshold(40);
112 
113     //获取边缘
114     Mat edges;
115     edges = morpho.getEdges(image);
116 
117     //得到角点
118     Mat corners;
119     corners = morpho.getCorners(image);
120 
121     namedWindow("边缘");
122     imshow("边缘", edges);
123 
124     namedWindow("角点");
125     imshow("角点", corners);
126 
127     waitKey();
128     return 0;
129 }
130     

 

形态学滤波(3):使用形态学滤波对图像进行边缘及角点检测.