1 #include2 #include 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 (2, i) = 1; 28 cross.at (i, 2) = 1; 29 } 30 31 //创建菱形元素 32 diamond.at (0, 0) = 0; 33 diamond.at (0, 1) = 0; 34 diamond.at (1, 0) = 0; 35 diamond.at (4, 4) = 0; 36 diamond.at (3, 4) = 0; 37 diamond.at (4, 3) = 0; 38 diamond.at (4, 0) = 0; 39 diamond.at (4, 1) = 0; 40 diamond.at (3, 0) = 0; 41 diamond.at (0, 4) = 0; 42 diamond.at (0, 3) = 0; 43 diamond.at (1, 4) = 0; 44 45 //创建X形元素 46 for (int i = 0; i < 5; i++) { 47 x.at (i, i) = 1; 48 x.at (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_ ::const_iterator it = binary.begin (); 77 Mat_ ::const_iterator itend = binary.end (); 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