Subversion Repositories OpenCV2-Cookbook

Rev

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
#include <iostream>
19
#include <vector>
20
#include <opencv2/core/core.hpp>
21
#include <opencv2/imgproc/imgproc.hpp>
22
#include <opencv2/highgui/highgui.hpp>
23
 
24
#include "linefinder.h"
25
#include "edgedetector.h"
26
 
27
#define PI 3.1415926
28
 
29
int main()
30
{
31
        // Read input image
32
        cv::Mat image= cv::imread("../road.jpg",0);
33
        if (!image.data)
34
                return 0;
35
 
36
    // Display the image
37
        cv::namedWindow("Original Image");
38
        cv::imshow("Original Image",image);
39
 
40
        // Compute Sobel
41
        EdgeDetector ed;
42
        ed.computeSobel(image);
43
 
44
    // Display the Sobel orientation
45
        cv::namedWindow("Sobel (orientation)");
46
        cv::imshow("Sobel (orientation)",ed.getSobelOrientationImage());
47
        cv::imwrite("ori.bmp",ed.getSobelOrientationImage());
48
 
49
    // Display the Sobel low threshold
50
        cv::namedWindow("Sobel (low threshold)");
51
        cv::imshow("Sobel (low threshold)",ed.getBinaryMap(125));
52
 
53
    // Display the Sobel high threshold
54
        cv::namedWindow("Sobel (high threshold)");
55
        cv::imshow("Sobel (high threshold)",ed.getBinaryMap(350));
56
 
57
        // Apply Canny algorithm
58
        cv::Mat contours;
59
        cv::Canny(image,contours,125,350);
60
        cv::Mat contoursInv;
61
        cv::threshold(contours,contoursInv,128,255,cv::THRESH_BINARY_INV);
62
 
63
    // Display the image of contours
64
        cv::namedWindow("Canny Contours");
65
        cv::imshow("Canny Contours",contoursInv);
66
 
67
        // Create a test image
68
        cv::Mat test(200,200,CV_8U,cv::Scalar(0));
69
        cv::line(test,cv::Point(100,0),cv::Point(200,200),cv::Scalar(255));
70
        cv::line(test,cv::Point(0,50),cv::Point(200,200),cv::Scalar(255));
71
        cv::line(test,cv::Point(0,200),cv::Point(200,0),cv::Scalar(255));
72
        cv::line(test,cv::Point(200,0),cv::Point(0,200),cv::Scalar(255));
73
        cv::line(test,cv::Point(100,0),cv::Point(100,200),cv::Scalar(255));
74
        cv::line(test,cv::Point(0,100),cv::Point(200,100),cv::Scalar(255));
75
 
76
    // Display the test image
77
        cv::namedWindow("Test Image");
78
        cv::imshow("Test Image",test);
79
        cv::imwrite("test.bmp",test);
80
 
81
        // Hough tranform for line detection
82
        std::vector<cv::Vec2f> lines;
83
        cv::HoughLines(contours,lines,1,PI/180,60);
84
 
85
        // Draw the lines
86
        cv::Mat result(contours.rows,contours.cols,CV_8U,cv::Scalar(255));
87
        image.copyTo(result);
88
 
89
        std::cout << "Lines detected: " << lines.size() << std::endl;
90
 
91
        std::vector<cv::Vec2f>::const_iterator it= lines.begin();
92
        while (it!=lines.end()) {
93
 
94
                float rho= (*it)[0];   // first element is distance rho
95
                float theta= (*it)[1]; // second element is angle theta
96
 
97
                if (theta < PI/4. || theta > 3.*PI/4.) { // ~vertical line
98
 
99
                        // point of intersection of the line with first row
100
                        cv::Point pt1(rho/cos(theta),0);        
101
                        // point of intersection of the line with last row
102
                        cv::Point pt2((rho-result.rows*sin(theta))/cos(theta),result.rows);
103
                        // draw a white line
104
                        cv::line( result, pt1, pt2, cv::Scalar(255), 1);
105
 
106
                } else { // ~horizontal line
107
 
108
                        // point of intersection of the line with first column
109
                        cv::Point pt1(0,rho/sin(theta));        
110
                        // point of intersection of the line with last column
111
                        cv::Point pt2(result.cols,(rho-result.cols*cos(theta))/sin(theta));
112
                        // draw a white line
113
                        cv::line( result, pt1, pt2, cv::Scalar(255), 1);
114
                }
115
 
116
                std::cout << "line: (" << rho << "," << theta << ")\n";
117
 
118
                ++it;
119
        }
120
 
121
    // Display the detected line image
122
        cv::namedWindow("Detected Lines with Hough");
123
        cv::imshow("Detected Lines with Hough",result);
124
 
125
        // Create LineFinder instance
126
        LineFinder ld;
127
 
128
        // Set probabilistic Hough parameters
129
        ld.setLineLengthAndGap(100,20);
130
        ld.setMinVote(80);
131
 
132
        // Detect lines
133
        std::vector<cv::Vec4i> li= ld.findLines(contours);
134
        ld.drawDetectedLines(image);
135
        cv::namedWindow("Detected Lines with HoughP");
136
        cv::imshow("Detected Lines with HoughP",image);
137
 
138
        std::vector<cv::Vec4i>::const_iterator it2= li.begin();
139
        while (it2!=li.end()) {
140
 
141
                std::cout << "(" << (*it2)[0] << ","<< (*it2)[1]<< ")-("
142
                             << (*it2)[2]<< "," << (*it2)[3] << ")" <<std::endl;
143
 
144
                ++it2;
145
        }
146
 
147
        // Display one line
148
        image= cv::imread("../road.jpg",0);
149
        int n=0;
150
        cv::line(image, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
151
        cv::namedWindow("One line of the Image");
152
        cv::imshow("One line of the Image",image);
153
 
154
        // Extract the contour pixels of the first detected line
155
        cv::Mat oneline(image.size(),CV_8U,cv::Scalar(0));
156
        cv::line(oneline, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
157
        cv::bitwise_and(contours,oneline,oneline);
158
        cv::Mat onelineInv;
159
        cv::threshold(oneline,onelineInv,128,255,cv::THRESH_BINARY_INV);
160
        cv::namedWindow("One line");
161
        cv::imshow("One line",onelineInv);
162
 
163
        std::vector<cv::Point> points;
164
 
165
        // Iterate over the pixels to obtain all point positions
166
        for( int y = 0; y < oneline.rows; y++ ) {
167
 
168
                uchar* rowPtr = oneline.ptr<uchar>(y);
169
 
170
                for( int x = 0; x < oneline.cols; x++ ) {
171
 
172
                    // if on a contour
173
                        if (rowPtr[x]) {
174
 
175
                                points.push_back(cv::Point(x,y));
176
                        }
177
                }
178
    }
179
 
180
        // find the best fitting line
181
        cv::Vec4f line;
182
        cv::fitLine(cv::Mat(points),line,CV_DIST_L2,0,0.01,0.01);
183
 
184
        std::cout << "line: (" << line[0] << "," << line[1] << ")(" << line[2] << "," << line[3] << ")\n";
185
 
186
        int x0= line[2];
187
        int y0= line[3];
188
        int x1= x0-200*line[0];
189
        int y1= y0-200*line[1];
190
        image= cv::imread("../road.jpg",0);
191
        cv::line(image,cv::Point(x0,y0),cv::Point(x1,y1),cv::Scalar(0),3);
192
        cv::namedWindow("Estimated line");
193
        cv::imshow("Estimated line",image);
194
 
195
        // eliminate inconsistent lines
196
        ld.removeLinesOfInconsistentOrientations(ed.getOrientation(),0.4,0.1);
197
 
198
   // Display the detected line image
199
        image= cv::imread("../road.jpg",0);
200
        ld.drawDetectedLines(image);
201
        cv::namedWindow("Detected Lines (2)");
202
        cv::imshow("Detected Lines (2)",image);
203
 
204
        // Create a Hough accumulator
205
        cv::Mat acc(200,180,CV_8U,cv::Scalar(0));
206
 
207
        // Choose a point
208
        int x=50, y=30;
209
 
210
        // loop over all angles
211
        for (int i=0; i<180; i++) {
212
 
213
                double theta= i*PI/180.;
214
 
215
                // find corresponding rho value 
216
                double rho= x*cos(theta)+y*sin(theta);
217
                int j= static_cast<int>(rho+100.5);
218
 
219
                std::cout << i << "," << j << std::endl;
220
 
221
                // increment accumulator
222
                acc.at<uchar>(j,i)++;
223
        }
224
 
225
        cv::imwrite("hough1.bmp",acc*100);
226
 
227
        // Choose a second point
228
        x=30, y=10;
229
 
230
        // loop over all angles
231
        for (int i=0; i<180; i++) {
232
 
233
                double theta= i*PI/180.;
234
                double rho= x*cos(theta)+y*sin(theta);
235
                int j= static_cast<int>(rho+100.5);
236
 
237
                acc.at<uchar>(j,i)++;
238
        }
239
 
240
        cv::namedWindow("Hough Accumulator");
241
        cv::imshow("Hough Accumulator",acc*100);
242
        cv::imwrite("hough2.bmp",acc*100);
243
 
244
        // Detect circles
245
        image= cv::imread("../chariot.jpg",0);
246
        cv::GaussianBlur(image,image,cv::Size(5,5),1.5);
247
        std::vector<cv::Vec3f> circles;
248
        cv::HoughCircles(image, circles, CV_HOUGH_GRADIENT,
249
                2,   // accumulator resolution (size of the image / 2) 
250
                50,  // minimum distance between two circles
251
                200, // Canny high threshold 
252
                100, // minimum number of votes 
253
                25, 100); // min and max radius
254
 
255
        std::cout << "Circles: " << circles.size() << std::endl;
256
 
257
        // Draw the circles
258
        image= cv::imread("../chariot.jpg",0);
259
        std::vector<cv::Vec3f>::const_iterator itc= circles.begin();
260
 
261
        while (itc!=circles.end()) {
262
 
263
          cv::circle(image,
264
                  cv::Point((*itc)[0], (*itc)[1]), // circle centre
265
                  (*itc)[2], // circle radius
266
                  cv::Scalar(255), // color 
267
                  2); // thickness
268
 
269
          ++itc;       
270
        }
271
 
272
        cv::namedWindow("Detected Circles");
273
        cv::imshow("Detected Circles",image);
274
 
275
        cv::waitKey();
276
        return 0;
277
}