Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | /*------------------------------------------------------------------------------------------*\ |
2 | This file contains material supporting chapter 7 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 LINEF |
||
19 | #define LINEF |
||
20 | |||
21 | #include <opencv2/core/core.hpp> |
||
22 | #include <opencv2/imgproc/imgproc.hpp> |
||
23 | #define PI 3.1415926 |
||
24 | |||
25 | class LineFinder { |
||
26 | |||
27 | private: |
||
28 | |||
29 | // original image |
||
30 | cv::Mat img; |
||
31 | |||
32 | // vector containing the end points |
||
33 | // of the detected lines |
||
34 | std::vector<cv::Vec4i> lines; |
||
35 | |||
36 | // accumulator resolution parameters |
||
37 | double deltaRho; |
||
38 | double deltaTheta; |
||
39 | |||
40 | // minimum number of votes that a line |
||
41 | // must receive before being considered |
||
42 | int minVote; |
||
43 | |||
44 | // min length for a line |
||
45 | double minLength; |
||
46 | |||
47 | // max allowed gap along the line |
||
48 | double maxGap; |
||
49 | |||
50 | public: |
||
51 | |||
52 | // Default accumulator resolution is 1 pixel by 1 degree |
||
53 | // no gap, no mimimum length |
||
54 | LineFinder() : deltaRho(1), deltaTheta(PI/180), minVote(10), minLength(0.), maxGap(0.) {} |
||
55 | |||
56 | // Set the resolution of the accumulator |
||
57 | void setAccResolution(double dRho, double dTheta) { |
||
58 | |||
59 | deltaRho= dRho; |
||
60 | deltaTheta= dTheta; |
||
61 | } |
||
62 | |||
63 | // Set the minimum number of votes |
||
64 | void setMinVote(int minv) { |
||
65 | |||
66 | minVote= minv; |
||
67 | } |
||
68 | |||
69 | // Set line length and gap |
||
70 | void setLineLengthAndGap(double length, double gap) { |
||
71 | |||
72 | minLength= length; |
||
73 | maxGap= gap; |
||
74 | } |
||
75 | |||
76 | // Apply probabilistic Hough Transform |
||
77 | std::vector<cv::Vec4i> findLines(cv::Mat& binary) { |
||
78 | |||
79 | lines.clear(); |
||
80 | cv::HoughLinesP(binary,lines,deltaRho,deltaTheta,minVote, minLength, maxGap); |
||
81 | |||
82 | return lines; |
||
83 | } |
||
84 | |||
85 | // Draw the detected lines on an image |
||
86 | void drawDetectedLines(cv::Mat &image, cv::Scalar color=cv::Scalar(255,255,255)) { |
||
87 | |||
88 | // Draw the lines |
||
89 | std::vector<cv::Vec4i>::const_iterator it2= lines.begin(); |
||
90 | |||
91 | while (it2!=lines.end()) { |
||
92 | |||
93 | cv::Point pt1((*it2)[0],(*it2)[1]); |
||
94 | cv::Point pt2((*it2)[2],(*it2)[3]); |
||
95 | |||
96 | cv::line( image, pt1, pt2, color); |
||
97 | |||
98 | ++it2; |
||
99 | } |
||
100 | } |
||
101 | |||
102 | // Eliminates lines that do not have an orientation equals to |
||
103 | // the ones specified in the input matrix of orientations |
||
104 | // At least the given percentage of pixels on the line must |
||
105 | // be within plus or minus delta of the corresponding orientation |
||
106 | std::vector<cv::Vec4i> removeLinesOfInconsistentOrientations( |
||
107 | const cv::Mat &orientations, double percentage, double delta) { |
||
108 | |||
109 | std::vector<cv::Vec4i>::iterator it= lines.begin(); |
||
110 | |||
111 | // check all lines |
||
112 | while (it!=lines.end()) { |
||
113 | |||
114 | // end points |
||
115 | int x1= (*it)[0]; |
||
116 | int y1= (*it)[1]; |
||
117 | int x2= (*it)[2]; |
||
118 | int y2= (*it)[3]; |
||
119 | |||
120 | // line orientation + 90o to get the parallel line |
||
121 | double ori1= atan2(static_cast<double>(y1-y2),static_cast<double>(x1-x2))+PI/2; |
||
122 | if (ori1>PI) ori1= ori1-2*PI; |
||
123 | |||
124 | double ori2= atan2(static_cast<double>(y2-y1),static_cast<double>(x2-x1))+PI/2; |
||
125 | if (ori2>PI) ori2= ori2-2*PI; |
||
126 | |||
127 | // for all points on the line |
||
128 | cv::LineIterator lit(orientations,cv::Point(x1,y1),cv::Point(x2,y2)); |
||
129 | int i,count=0; |
||
130 | for(i = 0, count=0; i < lit.count; i++, ++lit) { |
||
131 | |||
132 | float ori= *(reinterpret_cast<float *>(*lit)); |
||
133 | |||
134 | // is line orientation similar to gradient orientation ? |
||
135 | if (std::min(fabs(ori-ori1),fabs(ori-ori2))<delta) |
||
136 | count++; |
||
137 | |||
138 | } |
||
139 | |||
140 | double consistency= count/static_cast<double>(i); |
||
141 | |||
142 | // set to zero lines of inconsistent orientation |
||
143 | if (consistency < percentage) { |
||
144 | |||
145 | (*it)[0]=(*it)[1]=(*it)[2]=(*it)[3]=0; |
||
146 | |||
147 | } |
||
148 | |||
149 | ++it; |
||
150 | } |
||
151 | |||
152 | return lines; |
||
153 | } |
||
154 | }; |
||
155 | |||
156 | |||
157 | #endif |