teste.cpp
Go to the documentation of this file.
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 <ros/ros.h> //Includes all the headers necessary to use the most common public pieces of the ROS system.
25 #include <image_transport/image_transport.h> //Use image_transport for publishing and subscribing to images in ROS
26 #include <cv_bridge/cv_bridge.h> //Use cv_bridge to convert between ROS and OpenCV Image formats
27 #include <sensor_msgs/image_encodings.h> //Include some useful constants for image encoding. Refer to: http://www.ros.org/doc/api/sensor_msgs/html/namespacesensor__msgs_1_1image__encodings.html for more info.
28 
29 #include "linefinder.h"
30 #include "edgedetector.h"
31 
32 #define PI 3.1415926
33 namespace enc = sensor_msgs::image_encodings;
34 
35 //Declare a string with the name of the window that we will create using OpenCV where processed images will be displayed.
36 static const char WINDOW1[] = "Image Processed";
37 static const char WINDOW0[] = "Image Raw";
38 
39 //Use method of ImageTransport to create image publisher
40 image_transport::Publisher pub;
41 
42  int imageCallback(const sensor_msgs::ImageConstPtr& original_image)
43 {
44  int x=0 , y=0;
45  //Convert from the ROS image message to a CvImage suitable for working with OpenCV for processing
46  cv_bridge::CvImagePtr cv_ptr;
47  cv::Mat im_gray; /* imagem recebida em niveis de cinza*/
48  cv::Mat YCbCr;
49  cv::Mat subImg;
50  cv::Mat cv_clone;
51 
52  try
53  {
54 // Always copy, returning a mutable CvImage
55 // OpenCV expects color images to use BGR channel order.
56  cv_ptr = cv_bridge::toCvCopy(original_image, enc::BGR8);
57  cv_clone = cv_ptr->image.clone();
58 
59  }
60  catch (cv_bridge::Exception& e)
61  {
62 // if there is an error during conversion, display it
63  ROS_ERROR("tutorialROSOpenCV::main.cpp::cv_bridge exception: %s", e.what());
64  return 0;
65  }
66 
67  // Read input image
68  cv::Mat image;
69  cv_clone.copyTo(image);
70  if (!image.data)
71  return 0;
72 
73  // Display the image
74 // cv::namedWindow("Original Image");
75 // cv::imshow("Original Image",image);
76 // cv::waitKey(0);
77 
78  // Compute Sobel
79  EdgeDetector ed;
80  ed.computeSobel(image);
81 
82  // Display the Sobel orientation
83  cv::namedWindow("Sobel (orientation)");
84  cv::imshow("Sobel (orientation)",ed.getSobelOrientationImage());
85  cv::waitKey(3);
86  cv::imwrite("ori.bmp",ed.getSobelOrientationImage());
87 
88  // Display the Sobel low threshold
89  cv::namedWindow("Sobel (low threshold)");
90  cv::imshow("Sobel (low threshold)",ed.getBinaryMap(125));
91  cv::waitKey(3);
92  // Display the Sobel high threshold
93  cv::namedWindow("Sobel (high threshold)");
94  cv::imshow("Sobel (high threshold)",ed.getBinaryMap(350));
95  cv::waitKey(3);
96  // Apply Canny algorithm
97  cv::Mat contours;
98  cv::Canny(image,contours,125,350);
99  cv::Mat contoursInv;
100  cv::threshold(contours,contoursInv,128,255,cv::THRESH_BINARY_INV);
101 
102  // Display the image of contours
103  cv::namedWindow("Canny Contours");
104  cv::imshow("Canny Contours",contoursInv);
105  cv::waitKey(3);
106 
107  // Hough tranform for line detection
108  std::vector<cv::Vec2f> lines;
109  cv::HoughLines(contours,lines,1,(75*PI)/180,60);
110 
111  // Draw the lines
112  cv::Mat result(contours.rows,contours.cols,CV_8U,cv::Scalar(255));
113  image.copyTo(result);
114 
115  std::cout << "Lines detected: " << lines.size() << std::endl;
116 
117  std::vector<cv::Vec2f>::const_iterator it= lines.begin();
118  while (it!=lines.end()) {
119 
120  float rho= (*it)[0]; // first element is distance rho
121  float theta= (*it)[1]; // second element is angle theta
122 
123  if (theta < PI/4. || theta > 3.*PI/4.) { // ~vertical line
124 
125  // point of intersection of the line with first row
126  cv::Point pt1(rho/cos(theta),0);
127  // point of intersection of the line with last row
128  cv::Point pt2((rho-result.rows*sin(theta))/cos(theta),result.rows);
129  // draw a white line
130  cv::line( result, pt1, pt2, cv::Scalar(255), 1);
131 
132  } else { // ~horizontal line
133 
134  // point of intersection of the line with first column
135  cv::Point pt1(0,rho/sin(theta));
136  // point of intersection of the line with last column
137  cv::Point pt2(result.cols,(rho-result.cols*cos(theta))/sin(theta));
138  // draw a white line
139  cv::line( result, pt1, pt2, cv::Scalar(255), 1);
140  }
141 
142  std::cout << "line: (" << rho << "," << theta << ")\n";
143 
144  ++it;
145  }
146 
147  // Display the detected line image
148  cv::namedWindow("Detected Lines with Hough");
149  cv::imshow("Detected Lines with Hough",result);
150  cv::waitKey(3);
151  // Create LineFinder instance
152  LineFinder ld;
153 
154  // Set probabilistic Hough parameters
155  ld.setLineLengthAndGap(15,40);
156  ld.setMinVote(50);
157 
158  // Detect lines
159  std::vector<cv::Vec4i> li= ld.findLines(contours);
160  ld.drawDetectedLines(image);
161  cv::namedWindow("Detected Lines with HoughP");
162  cv::imshow("Detected Lines with HoughP",image);
163 // cv::waitKey(0);
164 
165  std::vector<cv::Vec4i>::const_iterator it2= li.begin();
166  while (it2!=li.end()) {
167 
168  std::cout << "(" << (*it2)[0] << ","<< (*it2)[1]<< ")-("
169  << (*it2)[2]<< "," << (*it2)[3] << ")" <<std::endl;
170 
171  ++it2;
172  }
173 
174  // Display one line
175 // image= cv::imread("../road.jpg",0);
176  int n=0;
177  cv::line(image, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
178  cv::namedWindow("One line of the Image");
179  cv::imshow("One line of the Image",image);
180 
181  // Extract the contour pixels of the first detected line
182  cv::Mat oneline(image.size(),CV_8U,cv::Scalar(0));
183  cv::line(oneline, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
184  cv::bitwise_and(contours,oneline,oneline);
185  cv::line(oneline, cv::Point(li[n+1][0],li[n+1][1]),cv::Point(li[n+1][2],li[n+1][3]),cv::Scalar(255),5);
186  cv::bitwise_and(contours,oneline,oneline);
187 // cv::bitwise_and(contours,secline,secline);
188  cv::Mat onelineInv;
189 // cv::threshold(oneline,onelineInv,128,255,cv::THRESH_BINARY_INV);
190  cv::adaptiveThreshold(oneline, onelineInv, 128, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 3, 5);
191  cv::namedWindow("One line");
192  cv::imshow("One line",onelineInv);
193 
194  std::vector<cv::Point> points;
195 
196  // Iterate over the pixels to obtain all point positions
197  for( int y = 0; y < oneline.rows; y++ ) {
198 
199  uchar* rowPtr = oneline.ptr<uchar>(y);
200 
201  for( int x = 0; x < oneline.cols; x++ ) {
202 
203  // if on a contour
204  if (rowPtr[x]) {
205 
206  points.push_back(cv::Point(x,y));
207  }
208  }
209  }
210 
211  // find the best fitting line
212  cv::Vec4f line;
213  cv::fitLine(cv::Mat(points),line,CV_DIST_L2,0,0.01,0.01);
214 
215  std::cout << "line: (" << line[0] << "," << line[1] << ")(" << line[2] << "," << line[3] << ")\n";
216 
217  int x0= line[2];
218  int y0= line[3];
219  int x1= x0-200*line[0];
220  int y1= y0-200*line[1];
221 // image= cv::imread("../road.jpg",0);
222  cv::line(image,cv::Point(x0,y0),cv::Point(x1,y1),cv::Scalar(0),3);
223  cv::namedWindow("Estimated line");
224  cv::imshow("Estimated line",image);
225 
226  // eliminate inconsistent lines
228 
229  // Display the detected line image
230 // image= cv::imread("../road.jpg",0);
231  ld.drawDetectedLines(image);
232  cv::namedWindow("Detected Lines (2)");
233  cv::imshow("Detected Lines (2)",image);
234 
235  // Create a Hough accumulator
236  cv::Mat acc(200,180,CV_8U,cv::Scalar(0));
237 
238  // Choose a point
239  x=50, y=30;
240 
241  // loop over all angles
242  for (int i=0; i<180; i++) {
243 
244  double theta= i*PI/180.;
245 
246  // find corresponding rho value
247  double rho= x*cos(theta)+y*sin(theta);
248  int j= static_cast<int>(rho+100.5);
249 
250  std::cout << i << "," << j << std::endl;
251 
252  // increment accumulator
253  acc.at<uchar>(j,i)++;
254  }
255 
256 // cv::imwrite("hough1.bmp",acc*100);
257 
258  // Choose a second point
259  x=30, y=10;
260 
261  // loop over all angles
262  for (int i=0; i<180; i++) {
263 
264  double theta= i*PI/180.;
265  double rho= x*cos(theta)+y*sin(theta);
266  int j= static_cast<int>(rho+100.5);
267 
268  acc.at<uchar>(j,i)++;
269  }
270 
271  cv::namedWindow("Hough Accumulator");
272  cv::imshow("Hough Accumulator",acc*100);
273  ROS_ERROR("-------ERROR -----");
274 // // cv::imwrite("hough2.bmp",acc*100);
275 // // ROS_ERROR("-------ERROR -----");
276 // // Detect circles
277 // // image= cv::imread("../chariot.jpg",0);
278 // cv::GaussianBlur(image,image,cv::Size(5,5),1.5);
279 // std::vector<cv::Vec3f> circles;
280 // // ROS_ERROR("-------ERROR -----");
281 // cv::HoughCircles(image, circles, CV_HOUGH_GRADIENT,
282 // 2, // accumulator resolution (size of the image / 2)
283 // 50, // minimum distance between two circles
284 // 200, // Canny high threshold
285 // 100, // minimum number of votes
286 // 25, 100); // min and max radius
287 // ROS_ERROR("-------ERROR -----");
288 // std::cout << "Circles: " << circles.size() << std::endl;
289 // ROS_ERROR("-------ERROR -----");
290 // // Draw the circles
291 // // image= cv::imread("../chariot.jpg",0);
292 // std::vector<cv::Vec3f>::const_iterator itc= circles.begin();
293 // ROS_ERROR("-------ERROR -----");
294 // while (itc!=circles.end()) {
295 //
296 // cv::circle(image,
297 // cv::Point((*itc)[0], (*itc)[1]), // circle centre
298 // (*itc)[2], // circle radius
299 // cv::Scalar(255), // color
300 // 2); // thickness
301 //
302 // ++itc;
303 // }
304 //
305 //
306 // cv::namedWindow("Detected Circles");
307 // cv::imshow("Detected Circles",image);
308 
309  cv::waitKey(3);
310  return 0;
311 }
312 
313 
317 int main(int argc, char **argv)
318 {
319  ros::init(argc, argv, "test");
320 
321  ros::NodeHandle nh;
322  /* Create an ImageTransport instance, initializing it with our NodeHandle. */
323  image_transport::ImageTransport it(nh);
324  /* OpenCV HighGUI call to create a display window on start-up. */
325  cv::namedWindow(WINDOW0, CV_WINDOW_AUTOSIZE);
326  cv::namedWindow(WINDOW1, CV_WINDOW_AUTOSIZE);
327 
328  image_transport::Subscriber sub = it.subscribe("image", 1, imageCallback);
329  /* OpenCV HighGUI call to destroy a display window on shut-down. */
330  cv::destroyWindow(WINDOW0);
331  cv::destroyWindow(WINDOW1);
332 
333  pub = it.advertise("image_processed", 1);
334 
335  ros::spin();
336  ROS_INFO("tutorialROSOpenCV::main.cpp::No error.");
337 }
std::vector< cv::Vec4i > findLines(cv::Mat &binary)
Definition: linefinder.h:78
static const char WINDOW1[]
Definition: teste.cpp:36
void drawDetectedLines(cv::Mat &image, cv::Scalar color=cv::Scalar(255, 255, 255))
Definition: linefinder.h:87
void setMinVote(int minv)
Definition: linefinder.h:65
cv::Mat getSobelOrientationImage()
Definition: edgedetector.h:154
int main(int argc, char **argv)
Definition: teste.cpp:317
#define PI
Definition: teste.cpp:32
cv::Mat getOrientation()
Definition: edgedetector.h:126
image_transport::Publisher pub
Definition: teste.cpp:40
void setLineLengthAndGap(double length, double gap)
Definition: linefinder.h:71
std::vector< cv::Vec4i > removeLinesOfInconsistentOrientations(const cv::Mat &orientations, double percentage, double delta)
Definition: linefinder.h:107
static const char WINDOW0[]
Definition: teste.cpp:37
void computeSobel(const cv::Mat image, cv::Mat sobelX=cv::Mat(), cv::Mat sobelY=cv::Mat())
Definition: edgedetector.h:107
int imageCallback(const sensor_msgs::ImageConstPtr &original_image)
Definition: teste.cpp:42
cv::Mat getBinaryMap(double threshold)
Definition: edgedetector.h:132


road_recognition
Author(s): Ricardo Morais
autogenerated on Mon Mar 2 2015 01:32:51