Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | /*------------------------------------------------------------------------------------------*\ |
2 | This file contains material supporting chapter 5 of the cookbook: |
||
3 | Computer Vision Programming using the OpenCV Library. |
||
4 | by Robert Laganiere, Packt Publishing, 2011. |
||
5 | |||
6 | This program is free software; permission is hereby granted to use, copy, modify, |
||
7 | and distribute this source code, or portions thereof, for any purpose, without fee, |
||
8 | subject to the restriction that the copyright notice may not be removed |
||
9 | or altered from any source or altered source distribution. |
||
10 | The software is released on an as-is basis and without any warranties of any kind. |
||
11 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. |
||
12 | The author disclaims all warranties with regard to this software, any use, |
||
13 | and any consequent failure, is purely the responsibility of the user. |
||
14 | |||
15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name |
||
16 | \*------------------------------------------------------------------------------------------*/ |
||
17 | |||
18 | #if !defined MORPHOF |
||
19 | #define MORPHOF |
||
20 | |||
21 | #include <opencv2/core/core.hpp> |
||
22 | #include <opencv2/imgproc/imgproc.hpp> |
||
23 | |||
24 | class MorphoFeatures { |
||
25 | |||
26 | private: |
||
27 | |||
28 | // threshold to produce binary image |
||
29 | int threshold; |
||
30 | // structuring elements used in corner detection |
||
31 | cv::Mat cross; |
||
32 | cv::Mat diamond; |
||
33 | cv::Mat square; |
||
34 | cv::Mat x; |
||
35 | |||
36 | void applyThreshold(cv::Mat& result) { |
||
37 | |||
38 | // Apply threshold on result |
||
39 | if (threshold>0) |
||
40 | cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV); |
||
41 | } |
||
42 | |||
43 | public: |
||
44 | |||
45 | MorphoFeatures() : threshold(-1), cross(5,5,CV_8U,cv::Scalar(0)), |
||
46 | diamond(5,5,CV_8U,cv::Scalar(1)), |
||
47 | square(5,5,CV_8U,cv::Scalar(1)), |
||
48 | x(5,5,CV_8U,cv::Scalar(0)){ |
||
49 | |||
50 | // Creating the cross-shaped structuring element |
||
51 | for (int i=0; i<5; i++) { |
||
52 | |||
53 | cross.at<uchar>(2,i)= 1; |
||
54 | cross.at<uchar>(i,2)= 1; |
||
55 | } |
||
56 | |||
57 | // Creating the diamond-shaped structuring element |
||
58 | diamond.at<uchar>(0,0)= 0; |
||
59 | diamond.at<uchar>(0,1)= 0; |
||
60 | diamond.at<uchar>(1,0)= 0; |
||
61 | diamond.at<uchar>(4,4)= 0; |
||
62 | diamond.at<uchar>(3,4)= 0; |
||
63 | diamond.at<uchar>(4,3)= 0; |
||
64 | diamond.at<uchar>(4,0)= 0; |
||
65 | diamond.at<uchar>(4,1)= 0; |
||
66 | diamond.at<uchar>(3,0)= 0; |
||
67 | diamond.at<uchar>(0,4)= 0; |
||
68 | diamond.at<uchar>(0,3)= 0; |
||
69 | diamond.at<uchar>(1,4)= 0; |
||
70 | |||
71 | // Creating the x-shaped structuring element |
||
72 | for (int i=0; i<5; i++) { |
||
73 | |||
74 | x.at<uchar>(i,i)= 1; |
||
75 | x.at<uchar>(4-i,i)= 1; |
||
76 | } |
||
77 | } |
||
78 | |||
79 | void setThreshold(int t) { |
||
80 | |||
81 | threshold= t; |
||
82 | } |
||
83 | |||
84 | int getThreshold() const { |
||
85 | |||
86 | return threshold; |
||
87 | } |
||
88 | |||
89 | cv::Mat getEdges(const cv::Mat &image) { |
||
90 | |||
91 | // Get the gradient image |
||
92 | cv::Mat result; |
||
93 | cv::morphologyEx(image,result,cv::MORPH_GRADIENT,cv::Mat()); |
||
94 | |||
95 | // Apply threshold to obtain a binary image |
||
96 | applyThreshold(result); |
||
97 | |||
98 | return result; |
||
99 | } |
||
100 | |||
101 | cv::Mat getCorners(const cv::Mat &image) { |
||
102 | |||
103 | cv::Mat result; |
||
104 | |||
105 | // Dilate with a cross |
||
106 | cv::dilate(image,result,cross); |
||
107 | |||
108 | // Erode with a diamond |
||
109 | cv::erode(result,result,diamond); |
||
110 | |||
111 | cv::Mat result2; |
||
112 | // Dilate with a X |
||
113 | cv::dilate(image,result2,x); |
||
114 | |||
115 | // Erode with a square |
||
116 | cv::erode(result2,result2,square); |
||
117 | |||
118 | // Corners are obtained by differencing |
||
119 | // the two closed images |
||
120 | cv::absdiff(result2,result,result); |
||
121 | |||
122 | // Apply threshold to obtain a binary image |
||
123 | applyThreshold(result); |
||
124 | |||
125 | return result; |
||
126 | } |
||
127 | |||
128 | void drawOnImage(const cv::Mat& binary, cv::Mat& image) { |
||
129 | |||
130 | cv::Mat_<uchar>::const_iterator it= binary.begin<uchar>(); |
||
131 | cv::Mat_<uchar>::const_iterator itend= binary.end<uchar>(); |
||
132 | |||
133 | // for each pixel |
||
134 | for (int i=0; it!= itend; ++it,++i) { |
||
135 | if (!*it) |
||
136 | cv::circle(image,cv::Point(i%image.step,i/image.step),5,cv::Scalar(255,0,0)); |
||
137 | } |
||
138 | } |
||
139 | }; |
||
140 | |||
141 | |||
142 | #endif |