Rev 3 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3 | Rev 5 | ||
---|---|---|---|
1 | /*------------------------------------------------------------------------------------------*\
|
1 | /*------------------------------------------------------------------------------------------*\
|
2 | This file contains material supporting chapter 7 of the cookbook:
|
2 | This file contains material supporting chapter 7 of the cookbook:
|
3 | Computer Vision Programming using the OpenCV Library.
|
3 | Computer Vision Programming using the OpenCV Library.
|
4 | by Robert Laganiere, Packt Publishing, 2011.
|
4 | by Robert Laganiere, Packt Publishing, 2011.
|
5 | 5 | ||
6 | This program is free software; permission is hereby granted to use, copy, modify,
|
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,
|
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
|
8 | subject to the restriction that the copyright notice may not be removed
|
9 | or altered from any source or altered source distribution.
|
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.
|
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.
|
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,
|
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.
|
13 | and any consequent failure, is purely the responsibility of the user.
|
14 |
|
14 |
|
15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
|
15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
|
16 | \*------------------------------------------------------------------------------------------*/
|
16 | \*------------------------------------------------------------------------------------------*/
|
17 | 17 | ||
18 | #include <iostream>
|
18 | #include <iostream>
|
19 | #include <vector>
|
19 | #include <vector>
|
20 | #include <opencv2/core/core.hpp>
|
20 | #include <opencv2/core/core.hpp>
|
21 | #include <opencv2/imgproc/imgproc.hpp>
|
21 | #include <opencv2/imgproc/imgproc.hpp>
|
22 | #include <opencv2/highgui/highgui.hpp>
|
22 | #include <opencv2/highgui/highgui.hpp>
|
23 | 23 | ||
24 | int main() |
24 | int main() |
25 | {
|
25 | {
|
26 | // Read input binary image
|
26 | // Read input binary image
|
27 | cv::Mat image= cv::imread("../binaryGroup.bmp",0); |
27 | cv::Mat image= cv::imread("../binaryGroup.bmp",0); |
28 | if (!image.data) |
28 | if (!image.data) |
29 | return 0; |
29 | return 0; |
30 | 30 | ||
31 | cv::namedWindow("Binary Image"); |
31 | cv::namedWindow("Binary Image"); |
32 | cv::imshow("Binary Image",image); |
32 | cv::imshow("Binary Image",image); |
33 | 33 | ||
34 | // Get the contours of the connected components
|
34 | // Get the contours of the connected components
|
35 | std::vector<std::vector<cv::Point>> contours; |
35 | std::vector<std::vector<cv::Point> > contours; |
36 | cv::findContours(image, |
36 | cv::findContours(image, |
37 | contours, // a vector of contours
|
37 | contours, // a vector of contours
|
38 | CV_RETR_EXTERNAL, // retrieve the external contours
|
38 | CV_RETR_EXTERNAL, // retrieve the external contours
|
39 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours |
39 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours |
40 | 40 | ||
41 | // Print contours' length
|
41 | // Print contours' length
|
42 | std::cout << "Contours: " << contours.size() << std::endl; |
42 | std::cout << "Contours: " << contours.size() << std::endl; |
43 | std::vector<std::vector<cv::Point>>::const_iterator itContours= contours.begin(); |
43 | std::vector<std::vector<cv::Point> >::const_iterator itContours= contours.begin(); |
44 | for ( ; itContours!=contours.end(); ++itContours) { |
44 | for ( ; itContours!=contours.end(); ++itContours) { |
45 | 45 | ||
46 | std::cout << "Size: " << itContours->size() << std::endl; |
46 | std::cout << "Size: " << itContours->size() << std::endl; |
47 | }
|
47 | }
|
48 | 48 | ||
49 | // draw black contours on white image
|
49 | // draw black contours on white image
|
50 | cv::Mat result(image.size(),CV_8U,cv::Scalar(255)); |
50 | cv::Mat result(image.size(),CV_8U,cv::Scalar(255)); |
51 | cv::drawContours(result,contours, |
51 | cv::drawContours(result,contours, |
52 | -1, // draw all contours |
52 | -1, // draw all contours |
53 | cv::Scalar(0), // in black |
53 | cv::Scalar(0), // in black |
54 | 2); // with a thickness of 2 |
54 | 2); // with a thickness of 2 |
55 | 55 | ||
56 | cv::namedWindow("Contours"); |
56 | cv::namedWindow("Contours"); |
57 | cv::imshow("Contours",result); |
57 | cv::imshow("Contours",result); |
58 | 58 | ||
59 | // Eliminate too short or too long contours
|
59 | // Eliminate too short or too long contours
|
60 | int cmin= 100; // minimum contour length |
60 | int cmin= 100; // minimum contour length |
61 | int cmax= 1000; // maximum contour length |
61 | int cmax= 1000; // maximum contour length |
62 | std::vector<std::vector<cv::Point>>::const_iterator itc= contours.begin(); |
62 | std::vector<std::vector<cv::Point> >::const_iterator itc= contours.begin(); |
63 | while (itc!=contours.end()) { |
63 | while (itc!=contours.end()) { |
64 | 64 | ||
65 | if (itc->size() < cmin || itc->size() > cmax) |
65 | if (itc->size() < cmin || itc->size() > cmax) |
66 | itc= contours.erase(itc); |
66 | itc= contours.erase(itc); |
67 | else
|
67 | else
|
68 | ++itc; |
68 | ++itc; |
69 | }
|
69 | }
|
70 | 70 | ||
71 | // draw contours on the original image
|
71 | // draw contours on the original image
|
72 | cv::Mat original= cv::imread("../group.jpg"); |
72 | cv::Mat original= cv::imread("../group.jpg"); |
73 | cv::drawContours(original,contours, |
73 | cv::drawContours(original,contours, |
74 | -1, // draw all contours |
74 | -1, // draw all contours |
75 | cv::Scalar(255,255,255), // in white |
75 | cv::Scalar(255,255,255), // in white |
76 | 2); // with a thickness of 2 |
76 | 2); // with a thickness of 2 |
77 | 77 | ||
78 | cv::namedWindow("Contours on Animals"); |
78 | cv::namedWindow("Contours on Animals"); |
79 | cv::imshow("Contours on Animals",original); |
79 | cv::imshow("Contours on Animals",original); |
80 | 80 | ||
81 | // Let's now draw black contours on white image
|
81 | // Let's now draw black contours on white image
|
82 | result.setTo(cv::Scalar(255)); |
82 | result.setTo(cv::Scalar(255)); |
83 | cv::drawContours(result,contours, |
83 | cv::drawContours(result,contours, |
84 | -1, // draw all contours |
84 | -1, // draw all contours |
85 | cv::Scalar(0), // in black |
85 | cv::Scalar(0), // in black |
86 | 1); // with a thickness of 1 |
86 | 1); // with a thickness of 1 |
87 | image= cv::imread("../binaryGroup.bmp",0); |
87 | image= cv::imread("../binaryGroup.bmp",0); |
88 | 88 | ||
89 | // testing the bounding box
|
89 | // testing the bounding box
|
90 | cv::Rect r0= cv::boundingRect(cv::Mat(contours[0])); |
90 | cv::Rect r0= cv::boundingRect(cv::Mat(contours[0])); |
91 | cv::rectangle(result,r0,cv::Scalar(0),2); |
91 | cv::rectangle(result,r0,cv::Scalar(0),2); |
92 | 92 | ||
93 | // testing the enclosing circle
|
93 | // testing the enclosing circle
|
94 | float radius; |
94 | float radius; |
95 | cv::Point2f center; |
95 | cv::Point2f center; |
96 | cv::minEnclosingCircle(cv::Mat(contours[1]),center,radius); |
96 | cv::minEnclosingCircle(cv::Mat(contours[1]),center,radius); |
97 | cv::circle(result,cv::Point(center),static_cast<int>(radius),cv::Scalar(0),2); |
97 | cv::circle(result,cv::Point(center),static_cast<int>(radius),cv::Scalar(0),2); |
98 | 98 | ||
99 | // cv::RotatedRect rrect= cv::fitEllipse(cv::Mat(contours[1]));
|
99 | // cv::RotatedRect rrect= cv::fitEllipse(cv::Mat(contours[1]));
|
100 | // cv::ellipse(result,rrect,cv::Scalar(0),2);
|
100 | // cv::ellipse(result,rrect,cv::Scalar(0),2);
|
101 | 101 | ||
102 | // testing the approximate polygon
|
102 | // testing the approximate polygon
|
103 | std::vector<cv::Point> poly; |
103 | std::vector<cv::Point> poly; |
104 | cv::approxPolyDP(cv::Mat(contours[2]),poly,5,true); |
104 | cv::approxPolyDP(cv::Mat(contours[2]),poly,5,true); |
105 | 105 | ||
106 | std::cout << "Polygon size: " << poly.size() << std::endl; |
106 | std::cout << "Polygon size: " << poly.size() << std::endl; |
107 | 107 | ||
108 | // Iterate over each segment and draw it
|
108 | // Iterate over each segment and draw it
|
109 | std::vector<cv::Point>::const_iterator itp= poly.begin(); |
109 | std::vector<cv::Point>::const_iterator itp= poly.begin(); |
110 | while (itp!=(poly.end()-1)) { |
110 | while (itp!=(poly.end()-1)) { |
111 | cv::line(result,*itp,*(itp+1),cv::Scalar(0),2); |
111 | cv::line(result,*itp,*(itp+1),cv::Scalar(0),2); |
112 | ++itp; |
112 | ++itp; |
113 | }
|
113 | }
|
114 | // last point linked to first point
|
114 | // last point linked to first point
|
115 | cv::line(result,*(poly.begin()),*(poly.end()-1),cv::Scalar(20),2); |
115 | cv::line(result,*(poly.begin()),*(poly.end()-1),cv::Scalar(20),2); |
116 | 116 | ||
117 | // testing the convex hull
|
117 | // testing the convex hull
|
118 | std::vector<cv::Point> hull; |
118 | std::vector<cv::Point> hull; |
119 | cv::convexHull(cv::Mat(contours[3]),hull); |
119 | cv::convexHull(cv::Mat(contours[3]),hull); |
120 | 120 | ||
121 | // Iterate over each segment and draw it
|
121 | // Iterate over each segment and draw it
|
122 | std::vector<cv::Point>::const_iterator it= hull.begin(); |
122 | std::vector<cv::Point>::const_iterator it= hull.begin(); |
123 | while (it!=(hull.end()-1)) { |
123 | while (it!=(hull.end()-1)) { |
124 | cv::line(result,*it,*(it+1),cv::Scalar(0),2); |
124 | cv::line(result,*it,*(it+1),cv::Scalar(0),2); |
125 | ++it; |
125 | ++it; |
126 | }
|
126 | }
|
127 | // last point linked to first point
|
127 | // last point linked to first point
|
128 | cv::line(result,*(hull.begin()),*(hull.end()-1),cv::Scalar(20),2); |
128 | cv::line(result,*(hull.begin()),*(hull.end()-1),cv::Scalar(20),2); |
129 | 129 | ||
130 | // testing the moments
|
130 | // testing the moments
|
131 | 131 | ||
132 | // iterate over all contours
|
132 | // iterate over all contours
|
133 | itc= contours.begin(); |
133 | itc= contours.begin(); |
134 | while (itc!=contours.end()) { |
134 | while (itc!=contours.end()) { |
135 | 135 | ||
136 | // compute all moments
|
136 | // compute all moments
|
137 | cv::Moments mom= cv::moments(cv::Mat(*itc++)); |
137 | cv::Moments mom= cv::moments(cv::Mat(*itc++)); |
138 | 138 | ||
139 | // draw mass center
|
139 | // draw mass center
|
140 | cv::circle(result, |
140 | cv::circle(result, |
141 | // position of mass center converted to integer
|
141 | // position of mass center converted to integer
|
142 | cv::Point(mom.m10/mom.m00,mom.m01/mom.m00), |
142 | cv::Point(mom.m10/mom.m00,mom.m01/mom.m00), |
143 | 2,cv::Scalar(0),2); // draw black dot |
143 | 2,cv::Scalar(0),2); // draw black dot |
144 | }
|
144 | }
|
145 | 145 | ||
146 | cv::namedWindow("Some Shape descriptors"); |
146 | cv::namedWindow("Some Shape descriptors"); |
147 | cv::imshow("Some Shape descriptors",result); |
147 | cv::imshow("Some Shape descriptors",result); |
148 | 148 | ||
149 | // New call to findContours but with CV_RETR_LIST flag
|
149 | // New call to findContours but with CV_RETR_LIST flag
|
150 | image= cv::imread("../binaryGroup.bmp",0); |
150 | image= cv::imread("../binaryGroup.bmp",0); |
151 | 151 | ||
152 | // Get the contours of the connected components
|
152 | // Get the contours of the connected components
|
153 | cv::findContours(image, |
153 | cv::findContours(image, |
154 | contours, // a vector of contours
|
154 | contours, // a vector of contours
|
155 | CV_RETR_LIST, // retrieve the external and internal contours
|
155 | CV_RETR_LIST, // retrieve the external and internal contours
|
156 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours |
156 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours |
157 | 157 | ||
158 | // draw black contours on white image
|
158 | // draw black contours on white image
|
159 | result.setTo(cv::Scalar(255)); |
159 | result.setTo(cv::Scalar(255)); |
160 | cv::drawContours(result,contours, |
160 | cv::drawContours(result,contours, |
161 | -1, // draw all contours |
161 | -1, // draw all contours |
162 | cv::Scalar(0), // in black |
162 | cv::Scalar(0), // in black |
163 | 2); // with a thickness of 2 |
163 | 2); // with a thickness of 2 |
164 | cv::namedWindow("All Contours"); |
164 | cv::namedWindow("All Contours"); |
165 | cv::imshow("All Contours",result); |
165 | cv::imshow("All Contours",result); |
166 | 166 | ||
167 | cv::waitKey(); |
167 | cv::waitKey(); |
168 | return 0; |
168 | return 0; |
169 | }
|
- | |
170 | 169 | }
|
|
- | 170 |