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