1+ #include < iostream>
2+ #include < numeric>
3+ #include < opencv2/core.hpp>
4+ #include < opencv2/highgui.hpp>
5+ #include < opencv2/imgproc.hpp>
6+
7+ #include " structIO.hpp"
8+ #include " dataStructures.h"
9+
10+ using namespace std ;
11+
12+ void loadCalibrationData (cv::Mat &P_rect_00, cv::Mat &R_rect_00, cv::Mat &RT)
13+ {
14+ RT.at <double >(0 ,0 ) = 7.533745e-03 ; RT.at <double >(0 ,1 ) = -9.999714e-01 ; RT.at <double >(0 ,2 ) = -6.166020e-04 ; RT.at <double >(0 ,3 ) = -4.069766e-03 ;
15+ RT.at <double >(1 ,0 ) = 1.480249e-02 ; RT.at <double >(1 ,1 ) = 7.280733e-04 ; RT.at <double >(1 ,2 ) = -9.998902e-01 ; RT.at <double >(1 ,3 ) = -7.631618e-02 ;
16+ RT.at <double >(2 ,0 ) = 9.998621e-01 ; RT.at <double >(2 ,1 ) = 7.523790e-03 ; RT.at <double >(2 ,2 ) = 1.480755e-02 ; RT.at <double >(2 ,3 ) = -2.717806e-01 ;
17+ RT.at <double >(3 ,0 ) = 0.0 ; RT.at <double >(3 ,1 ) = 0.0 ; RT.at <double >(3 ,2 ) = 0.0 ; RT.at <double >(3 ,3 ) = 1.0 ;
18+
19+ R_rect_00.at <double >(0 ,0 ) = 9.999239e-01 ; R_rect_00.at <double >(0 ,1 ) = 9.837760e-03 ; R_rect_00.at <double >(0 ,2 ) = -7.445048e-03 ; R_rect_00.at <double >(0 ,3 ) = 0.0 ;
20+ R_rect_00.at <double >(1 ,0 ) = -9.869795e-03 ; R_rect_00.at <double >(1 ,1 ) = 9.999421e-01 ; R_rect_00.at <double >(1 ,2 ) = -4.278459e-03 ; R_rect_00.at <double >(1 ,3 ) = 0.0 ;
21+ R_rect_00.at <double >(2 ,0 ) = 7.402527e-03 ; R_rect_00.at <double >(2 ,1 ) = 4.351614e-03 ; R_rect_00.at <double >(2 ,2 ) = 9.999631e-01 ; R_rect_00.at <double >(2 ,3 ) = 0.0 ;
22+ R_rect_00.at <double >(3 ,0 ) = 0 ; R_rect_00.at <double >(3 ,1 ) = 0 ; R_rect_00.at <double >(3 ,2 ) = 0 ; R_rect_00.at <double >(3 ,3 ) = 1 ;
23+
24+ P_rect_00.at <double >(0 ,0 ) = 7.215377e+02 ; P_rect_00.at <double >(0 ,1 ) = 0.000000e+00 ; P_rect_00.at <double >(0 ,2 ) = 6.095593e+02 ; P_rect_00.at <double >(0 ,3 ) = 0.000000e+00 ;
25+ P_rect_00.at <double >(1 ,0 ) = 0.000000e+00 ; P_rect_00.at <double >(1 ,1 ) = 7.215377e+02 ; P_rect_00.at <double >(1 ,2 ) = 1.728540e+02 ; P_rect_00.at <double >(1 ,3 ) = 0.000000e+00 ;
26+ P_rect_00.at <double >(2 ,0 ) = 0.000000e+00 ; P_rect_00.at <double >(2 ,1 ) = 0.000000e+00 ; P_rect_00.at <double >(2 ,2 ) = 1.000000e+00 ; P_rect_00.at <double >(2 ,3 ) = 0.000000e+00 ;
27+
28+ }
29+
30+ void showLidarTopview (std::vector<LidarPoint> &lidarPoints, cv::Size worldSize, cv::Size imageSize)
31+ {
32+ // create topview image
33+ cv::Mat topviewImg (imageSize, CV_8UC3, cv::Scalar (0 , 0 , 0 ));
34+
35+ // plot Lidar points into image
36+ for (auto it = lidarPoints.begin (); it != lidarPoints.end (); ++it)
37+ {
38+ float xw = (*it).x ; // world position in m with x facing forward from sensor
39+ float yw = (*it).y ; // world position in m with y facing left from sensor
40+
41+ int y = (-xw * imageSize.height / worldSize.height ) + imageSize.height ;
42+ int x = (-yw * imageSize.height / worldSize.height ) + imageSize.width / 2 ;
43+
44+ float zw = (*it).z ; // world position in m with y facing left from sensor
45+ if (zw > -1.40 ){
46+
47+ float val = it->x ;
48+ float maxVal = worldSize.height ;
49+ int red = min (255 , (int )(255 * abs ((val - maxVal) / maxVal)));
50+ int green = min (255 , (int )(255 * (1 - abs ((val - maxVal) / maxVal))));
51+ cv::circle (topviewImg, cv::Point (x, y), 5 , cv::Scalar (0 , green, red), -1 );
52+ }
53+ }
54+
55+ // plot distance markers
56+ float lineSpacing = 2.0 ; // gap between distance markers
57+ int nMarkers = floor (worldSize.height / lineSpacing);
58+ for (size_t i = 0 ; i < nMarkers; ++i)
59+ {
60+ int y = (-(i * lineSpacing) * imageSize.height / worldSize.height ) + imageSize.height ;
61+ cv::line (topviewImg, cv::Point (0 , y), cv::Point (imageSize.width , y), cv::Scalar (255 , 0 , 0 ));
62+ }
63+
64+ // display image
65+ string windowName = " Top-View Perspective of LiDAR data" ;
66+ cv::namedWindow (windowName, 2 );
67+ cv::imshow (windowName, topviewImg);
68+ cv::waitKey (0 ); // wait for key to be pressed
69+ }
70+
71+
72+ void clusterLidarWithROI (std::vector<BoundingBox> &boundingBoxes, std::vector<LidarPoint> &lidarPoints)
73+ {
74+ // store calibration data in OpenCV matrices
75+ cv::Mat P_rect_xx (3 ,4 ,cv::DataType<double >::type); // 3x4 projection matrix after rectification
76+ cv::Mat R_rect_xx (4 ,4 ,cv::DataType<double >::type); // 3x3 rectifying rotation to make image planes co-planar
77+ cv::Mat RT (4 ,4 ,cv::DataType<double >::type); // rotation matrix and translation vector
78+ loadCalibrationData (P_rect_xx, R_rect_xx, RT);
79+
80+ // loop over all Lidar points and associate them to a 2D bounding box
81+ cv::Mat X (4 , 1 , cv::DataType<double >::type);
82+ cv::Mat Y (3 , 1 , cv::DataType<double >::type);
83+
84+ for (auto it1 = lidarPoints.begin (); it1 != lidarPoints.end (); ++it1)
85+ {
86+ // assemble vector for matrix-vector-multiplication
87+ X.at <double >(0 , 0 ) = it1->x ;
88+ X.at <double >(1 , 0 ) = it1->y ;
89+ X.at <double >(2 , 0 ) = it1->z ;
90+ X.at <double >(3 , 0 ) = 1 ;
91+
92+ // project Lidar point into camera
93+ Y = P_rect_xx * R_rect_xx * RT * X;
94+ cv::Point pt;
95+ pt.x = Y.at <double >(0 , 0 ) / Y.at <double >(0 , 2 ); // pixel coordinates
96+ pt.y = Y.at <double >(1 , 0 ) / Y.at <double >(0 , 2 );
97+
98+ double shrinkFactor = 0.10 ;
99+ vector<vector<BoundingBox>::iterator> enclosingBoxes; // pointers to all bounding boxes which enclose the current Lidar point
100+ for (vector<BoundingBox>::iterator it2 = boundingBoxes.begin (); it2 != boundingBoxes.end (); ++it2)
101+ {
102+ // shrink current bounding box slightly to avoid having too many outlier points around the edges
103+ cv::Rect smallerBox;
104+ smallerBox.x = (*it2).roi .x + shrinkFactor * (*it2).roi .width / 2.0 ;
105+ smallerBox.y = (*it2).roi .y + shrinkFactor * (*it2).roi .height / 2.0 ;
106+ smallerBox.width = (*it2).roi .width * (1 - shrinkFactor);
107+ smallerBox.height = (*it2).roi .height * (1 - shrinkFactor);
108+
109+ // check wether point is within current bounding box
110+ if (smallerBox.contains (pt))
111+ {
112+ it2->lidarPoints .push_back (*it1);
113+ lidarPoints.erase (it1);
114+ it1--;
115+ break ;
116+ }
117+ } // eof loop over all bounding boxes
118+
119+ } // eof loop over all Lidar points
120+ }
121+
122+ int main ()
123+ {
124+ std::vector<LidarPoint> lidarPoints;
125+ readLidarPts (" ../dat/C53A3_currLidarPts.dat" , lidarPoints);
126+
127+ std::vector<BoundingBox> boundingBoxes;
128+ readBoundingBoxes (" ../dat/C53A3_currBoundingBoxes.dat" , boundingBoxes);
129+
130+ clusterLidarWithROI (boundingBoxes, lidarPoints);
131+ for (auto it = boundingBoxes.begin (); it != boundingBoxes.end (); ++it)
132+ {
133+ if (it->lidarPoints .size () > 0 )
134+ {
135+ showLidarTopview (it->lidarPoints , cv::Size (10.0 , 25.0 ), cv::Size (1000 , 2000 ));
136+ }
137+ }
138+
139+ return 0 ;
140+ }
0 commit comments