Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | /*------------------------------------------------------------------------------------------*\ |
2 | This file contains material supporting chapter 8 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 HARRISD |
||
19 | #define HARRISD |
||
20 | |||
21 | #include <vector> |
||
22 | #include <opencv2/core/core.hpp> |
||
23 | #include <opencv2/imgproc/imgproc.hpp> |
||
24 | #include <opencv2/highgui/highgui.hpp> |
||
25 | #include <opencv2/features2d/features2d.hpp> |
||
26 | |||
27 | class HarrisDetector { |
||
28 | |||
29 | private: |
||
30 | |||
31 | // 32-bit float image of corner strength |
||
32 | cv::Mat cornerStrength; |
||
33 | // 32-bit float image of thresholded corners |
||
34 | cv::Mat cornerTh; |
||
35 | // image of local maxima (internal) |
||
36 | cv::Mat localMax; |
||
37 | // size of neighbourhood for derivatives smoothing |
||
38 | int neighbourhood; |
||
39 | // aperture for gradient computation |
||
40 | int aperture; |
||
41 | // Harris parameter |
||
42 | double k; |
||
43 | // maximum strength for threshold computation |
||
44 | double maxStrength; |
||
45 | // calculated threshold (internal) |
||
46 | double threshold; |
||
47 | // size of neighbourhood for non-max suppression |
||
48 | int nonMaxSize; |
||
49 | // kernel for non-max suppression |
||
50 | cv::Mat kernel; |
||
51 | |||
52 | public: |
||
53 | |||
54 | HarrisDetector() : neighbourhood(3), aperture(3), k(0.1), maxStrength(0.0), threshold(0.01), nonMaxSize(3) { |
||
55 | |||
56 | setLocalMaxWindowSize(nonMaxSize); |
||
57 | } |
||
58 | |||
59 | // Create kernel used in non-maxima suppression |
||
60 | void setLocalMaxWindowSize(int size) { |
||
61 | |||
62 | nonMaxSize= size; |
||
63 | kernel.create(nonMaxSize,nonMaxSize,CV_8U); |
||
64 | } |
||
65 | |||
66 | // Compute Harris corners |
||
67 | void detect(const cv::Mat& image) { |
||
68 | |||
69 | // Harris computation |
||
70 | cv::cornerHarris(image,cornerStrength, |
||
71 | neighbourhood,// neighborhood size |
||
72 | aperture, // aperture size |
||
73 | k); // Harris parameter |
||
74 | |||
75 | // internal threshold computation |
||
76 | double minStrength; // not used |
||
77 | cv::minMaxLoc(cornerStrength,&minStrength,&maxStrength); |
||
78 | |||
79 | // local maxima detection |
||
80 | cv::Mat dilated; // temporary image |
||
81 | cv::dilate(cornerStrength,dilated,cv::Mat()); |
||
82 | cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ); |
||
83 | } |
||
84 | |||
85 | // Get the corner map from the computed Harris values |
||
86 | cv::Mat getCornerMap(double qualityLevel) { |
||
87 | |||
88 | cv::Mat cornerMap; |
||
89 | |||
90 | // thresholding the corner strength |
||
91 | threshold= qualityLevel*maxStrength; |
||
92 | cv::threshold(cornerStrength,cornerTh,threshold,255,cv::THRESH_BINARY); |
||
93 | |||
94 | // convert to 8-bit image |
||
95 | cornerTh.convertTo(cornerMap,CV_8U); |
||
96 | |||
97 | // non-maxima suppression |
||
98 | cv::bitwise_and(cornerMap,localMax,cornerMap); |
||
99 | |||
100 | return cornerMap; |
||
101 | } |
||
102 | |||
103 | // Get the feature points vector from the computed Harris values |
||
104 | void getCorners(std::vector<cv::Point> &points, double qualityLevel) { |
||
105 | |||
106 | // Get the corner map |
||
107 | cv::Mat cornerMap= getCornerMap(qualityLevel); |
||
108 | // Get the corners |
||
109 | getCorners(points, cornerMap); |
||
110 | } |
||
111 | |||
112 | // Get the feature points vector from the computed corner map |
||
113 | void getCorners(std::vector<cv::Point> &points, const cv::Mat& cornerMap) { |
||
114 | |||
115 | // Iterate over the pixels to obtain all feature points |
||
116 | for( int y = 0; y < cornerMap.rows; y++ ) { |
||
117 | |||
118 | const uchar* rowPtr = cornerMap.ptr<uchar>(y); |
||
119 | |||
120 | for( int x = 0; x < cornerMap.cols; x++ ) { |
||
121 | |||
122 | // if it is a feature point |
||
123 | if (rowPtr[x]) { |
||
124 | |||
125 | points.push_back(cv::Point(x,y)); |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | } |
||
130 | |||
131 | // Draw circles at feature point locations on an image |
||
132 | void drawOnImage(cv::Mat &image, const std::vector<cv::Point> &points, cv::Scalar color= cv::Scalar(255,255,255), int radius=3, int thickness=2) { |
||
133 | |||
134 | std::vector<cv::Point>::const_iterator it= points.begin(); |
||
135 | |||
136 | // for all corners |
||
137 | while (it!=points.end()) { |
||
138 | |||
139 | // draw a circle at each corner location |
||
140 | cv::circle(image,*it,radius,color,thickness); |
||
141 | ++it; |
||
142 | } |
||
143 | } |
||
144 | }; |
||
145 | |||
146 | #endif |