# udacity_sensor_fusion_camera_project_two **Repository Path**: libing02/udacity_sensor_fusion_camera_project_two ## Basic Information - **Project Name**: udacity_sensor_fusion_camera_project_two - **Description**: No description available - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-04-10 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## FP.1 Match 3D Objects loop all the bounding boxes in previous frame loop all the matches check if match.previous_keypoint inside the previous bounding box get the corresponding current_keypoint loop all the bounding boxes in current frame check if the currrent_keypoint inside the current bounding box if inside, count the number of match pair :(prevbox, currbox) find the max matches box in current frame, restore the bounding box pair in the result map. Note: in order to make the result stable, I make three steps : 1. when I compute the max match box, I wil also try to compute the ratio = prev_box_size/ curr_box_size. If the ratio is less than threshold, it means the box size change to much in those two frame, it should be something wrong. I will filter this match box out. 2. Besides the size of box, I will also compare the center position of the box, if the box position change too large (the euclidean distance is large than 100), I will also filter this box out. 3. If the matches points number of two boxes is less than 5, I will filter this box out. ## FP.2 Compute Lidar-based TTC First of all, we use Constant Velocity Model to compute TTC. The TTC compute process: 1. First, we need to find the x-position of object back in previous frame: distance_prev_x 2. Then, we need to find the x-position of object back in current frame: distance_curr_x 3. We compute the distance the object move: distance_x=distance_prev_x - distance_curr_x 4. We compute the velocity of the object : velocity_x = distance_x / delta_time 5. We compute the curr_nearest_distance of the object. (use another average statistic method to avoid outlier to the distance computation) 6. We assume the velocity of the object is same, then compute the TTC = curr_nearest_distance / velocity_x; Note: if the relative velocity_x is negative, the TTC should be maximum. In order to make the system stable, I implmenet two method to avoid ghost points. One is for velocity computation: We will use the following method to avoid outlier Lidar points to the velocity computation: 1. First, we will sort the Lidar points by x-position. 2. Then, we will pick top N (N=200) points. 3. We will use IQR method (the Q1=1/4 of top N points) to compute the center of the object back. 4. Finally, we use the average value of Q1-1, Q1, Q1+1 to compute the final value, as the center of object's back. Another is for nearest distance computation We will use the following method to avoid outlier Lidar points to the nearest distance computation: 1. First, we will sort the Lidar points by x-position. 2. Then, we will pick top N (N=200) points. 3. We will use IQR method (the Q1=1/10 of top N points) as the standard value. 4. In order to avoid ghost point in near, We will pick top 5 points of the points. If the distance of the point between standard value is more than 5cm, we will remove the point. ## FP.3 Associate Keypoint Correspondences with Bounding Boxes loop all the matches check if the matches.keypoint inside the bounding box if inside, add it to the vector In order to make the system stable, I implment two method to avoid wrong matches. Method 1st: compute the mean of matches euclidean distance. loop all the matches inside the vector compute the euclidean distance between the matches (previous keypoint and current keypoint) if the abs(mean-distance) > threshold (for example. 300) then remove this match. Because it's obviously wrong. Method 2nd: outer loop all the matches in the box get match point pair A inner loop all the matches in the box get match point pair B get the line from A to B compute the ratio of Previous and Current line's length; restore the ratio compute the average ratio value start from A compute the average ratio value of all points loop all the matches in the box if the average ratio start from A - average ratio of all points > threshold remove this match ## FP.4 Compute Camera-based TTC out_loop each matches in_loop each matches compute the distance ratio for each match pair save the distance ratio in a vector sort the distance ratio vector, find the median value of distance ratio. use the median distance ratio to compute the TTC. # Performance Evaluation To make it simple, we use constant velocity model, and the TTC only focus on the related two frames. So the performance of the TTC compute may not good enough. In the future, we may change to constant acceleration model, and use more frames to make the estimation more precise. ## FP.5 Performance Evaluation 1 _Lidar TTC Compute For TTC estimation, I think there will be two aspects can influence the estimation performance (ignore time used): 3.1 TTC computation estimation model (constant velocity, or constant acceleration) 3.2 The distance estimation of object (with lidar measurement) I think for lidar points, the distance information is precise. If we don't consider estimation model, if the lidar points is correctly match to its original object, the TTC computation should be precise. For lidar points, I think the main error may come in two ways: - The lidar points match to the wrong object. It means lidar points of object1 match to object2. This problem is very common. Because now we use Yolov3 to get the object rectangle from the image. But the detection is not so precise. The object in real world may have a lot of shape, but in here we use rectangle to represent it. In the future, we can use semantic segmentation to get more precise object boundary. - There is no object, but some points come. I think in real world, this problem may rise in sometime. Because we measure the lidar points by the light reflection. But for some object have big or small reflection feature, especially the mirror and water, there will be some ghost lidar points. It's hard to filter them out. I think we should handle them by some software technology. For example, we can get more precise tracking of the object. Some sudden come points will not be counted. In one word, we don't trust the points in one frame. We should trust the object which appear in several frames. Here i will mark some problems I found in the test: 1. In some cases, there are two bounding boxes found in front. The main lidar points belong to the leading vehicle. But there are a few points of leading vehicle are mismatch to the right vehicle. Understanding: This error maybe caused by the shrink operation. In order to filter out the outlier, we make the bounding box small. So some of its points are filter out. But when there is another bounding box near by with some intersection of that box. Maybe the points will be mismatched. Then will get another bounding box. Solution: Maybe we can use smaller box to compute the lidar. To filter more boundary points out. I make the float shrinkFactor = 0.30; this error is fix. I think , in the future, maybe we can don't use bounding box to filter the lidar points, we may need instance segmentation to filter the outlier points. That's more precise. And further, the shrinkFactor can change depends on the object's distance. If we get closer, we can change the shrinkFactor to get smaller box. Because for closer object, we don't need so much lidar points to get the enough information. 2. In some cases, there will be the front-front car's lidar came to the ROI of box. But it does not cause the error in TTC estimation. 3. When the front vehicle is stop, in some cases the lidar will measurement small movement. When we compute the TTC. The TTC will be very large. For this error, i guess it may cause by the lidar depth resolution or some lidar physical issue. 4. In some cases, the TTC compute will be very strange: the x-distance of previous frame will be very large. After checking the log, the reason is mismatch of bounding boxes. The bounding box has been match to another wrong box.But in most cases, the matching works well. See combination(SIFT, BRISK) ## FP.6 Performance Evaluation 2 _Camera TTC Compute For Camera-based TTC estimation, i make the tests of some combination and list performance frame by frame in the following table. If we ignore the process time, the SIFT-detector will have good performance. But it will take more than 120ms. It is unacceptable. Since our job is collision avoid system, it has strong real-time requirement. And the image come every 100ms, we also have a lot of other job to perform, i think the time used for detector and descriptor must be less than 10ms. So i think only FAST can match our requirement. I have computed all the combinations and store the result of them in the build/log/ directory. You will find them in that directory. In the following table, i have record all the combination and their result in test. By the way, I use iamge from 25 to 55, image_step=2. So there is 14 frames in the table. |col:the frame
row:detector
descriptor | 1 | 2| 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11| 12| 13 | 14 | |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| |AKAZE+AKAZE|8.88|9.01|9.89|10.44|8.70|7.43|8.76|9.02|7.02|8.50|9.41|12.17|18.67|59.29| |AKAZE+BRIEF|9.20|9.26|9.96|10.79|8.48|7.43|9.09|8.34|6.98|8.57|9.65|12.33|19.66|73.81| |AKAZE+BRISK|8.62|8.87|9.97|10.35|8.48|7.25|8.58|7.60|6.80|8.22|9.45|11.84|18.83|50.80| |AKAZE+FREAK|8.80|9.03|10.01|10.33|8.82|7.49|8.04|7.79|7.69|8.41|9.53|11.95|19.51|56.49| |AKAZE+ORB |8.73|8.92|9.34|10.52|8.30|7.25|8.59|8.27|7.17|8.89|9.81|12.56|19.75|65.62| |AKAZE+SIFT |8.98|8.95|9.91|10.78|8.42|7.64|8.56|8.73|7.02|8.79|9.86|11.92|18.93|61.28| |BRISK+BRIEF| 10.51| 10.19| 11.40| 11.66| 9.39| 7.91| 9.57| 7.33| 6.78| 7.55| 9.56| 12.61| 17.36| 52.23| |BRISK+BRISK| 11.04| 11.20| 14.78| 13.00| 9.12| 7.65| 8.66| 7.42| 6.87| 8.28| 9.01| 11.36| 18.49| 54.73| |BRISK+FREAK| 10.90| 12.14| 12.23| 11.67| 9.88| 8.23| 8.27| 8.17| 6.67| 8.15| 9.93| 12.30| 19.13| 52.58| |BRISK+ORB| 11.38| 11.73| 13.69| 11.63| 9.31| 8.07| 8.51| 7.45| 7.23| 8.40| 9.00| 11.66| 17.94| 55.47| |BRISK+SIFT| 11.60| 12.31| 16.53| 15.62| 12.54| 7.70| 9.25| 8.97| 7.47| 7.95| 9.72| 12.41| 17.67| 90.56| |FAST+BRIEF| 9.07| 10.64| 11.39| 12.78| 10.06| 7.56| 9.22| 7.11| 7.03| 8.22| 9.34| 12.03| 17.80| 53.56| |FAST+BRISK| 10.26| 10.04| 11.71| 11.66| 9.74| 7.69| 8.29| 6.56| 6.94| 8.14| 8.92| 11.53| 17.45| 44.41| |FAST+FREAK| 8.81| 12.65| 13.26| 11.66| 8.76| 7.41| 10.11| 6.98| 7.16| 8.24| 8.45| 11.42| 15.45| 48.89| |FAST+SIFT| 10.76| 10.83| 11.75| 11.99| 9.42| 7.58| 10.30| 7.41| 7.20| 8.22| 10.00| 11.79| 18.58| 51.68| |HARRIS+BRIEF| 9.77| 21.91| 13.60| 27.29| 14.67| 10.20| 22.37| 10.42| 11.11| 13.28| 24.49| 25.94| 46.00|-inf| |HARRIS+BRISK| 9.88| 12.82| 10.91| 13.57| 9.20| 10.23| 11.24| 9.21| 10.37| 12.34| 42.87| 16.16| 86.53|-inf| |HARRIS+FREAK| 7.73| 15.27| 12.46| 24.86| 6.72|104.66| 10.42| 11.40| 9.94| 16.55| 23.64| 52.77|-inf|-28.59| |HARRIS+ORB| 9.53| 13.58| 13.30| 18.97| 13.33| 10.20| 27.72| 7.27| 10.83| 12.61| 24.49| 25.94| 39.96|-inf| |HARRIS+SIFT| 9.53| 15.25| 13.60| 25.20| 13.33| 10.20| 27.72| 11.43| 12.10| 12.14| 24.49| 20.60| 91.67|-inf| |ORB+BRIEF| 11.32| 13.20| 13.63| 12.55| 9.16| 8.39| 10.90| 14.70| 10.12| 12.28| 16.50| 28.48| 30.38|-inf| |ORB+BRISK| 13.18| 15.70| 14.83| 16.49| 11.54| 8.60| 11.13| 12.20| 12.14| 15.55| 17.16| 40.22| 86.59|-inf| |ORB+FREAK| 8.96| 13.83| 12.82| 17.80| 10.95| 8.82| 17.24| 19.83| 14.64| 21.67| 56.58|541.19|-inf|-inf| |ORB+ORB| 11.23| 12.61| 15.47| 14.57| 13.05| 8.11| 11.44| 10.25| 10.34| 10.34| 12.97| 24.05| 28.61|-inf| |ORB+SIFT| 16.00| 14.08| 20.85| 20.36| 17.05| 9.41| 10.02| 12.09| 12.93| 11.14| 16.97| 43.11| 29.21|-inf| |SHITOMASI+BRIEF| 8.82| 10.11| 11.39| 12.08| 9.52| 8.13| 7.99| 7.16| 6.86| 7.74| 9.40| 10.23| 18.14| 47.26| |SHITOMASI+BRISK| 9.11| 9.80| 9.81| 11.23| 8.68| 7.84| 8.12| 6.95| 6.62| 7.37| 9.00| 9.81| 17.30| 40.95| |SHITOMASI+FREAK| 8.97| 9.46| 9.77| 10.74| 8.95| 7.63| 7.81| 6.93| 6.42| 7.52| 9.20| 9.80| 16.28| 43.50| |SHITOMASI+ORB| 8.25| 9.87| 10.73| 11.74| 9.18| 8.01| 7.78| 6.91| 6.89| 7.66| 9.32| 10.29| 18.00| 43.99| |SHITOMASI+SIFT| 8.86| 10.81| 11.33| 11.83| 9.03| 8.14| 8.56| 7.44| 6.91| 7.58| 9.41| 10.11| 18.01| 42.25| |SIFT+BRIEF| 9.02| 8.47| 10.28| 11.19| 9.21| 7.76| 7.63| 7.18| 6.93| 7.35| 8.83| 10.68| 15.47| 40.27| |SIFT+BRISK| 9.21| 8.71| 9.94| 10.40| 8.58| 7.25| 7.40| 6.77| 6.33| 6.88| 8.43| 10.16| 14.90| 40.30| |SIFT+FREAK| 9.05| 8.54| 9.44| 10.16| 8.60| 7.13| 6.74| 7.27| 6.63| 6.90| 8.44| 10.15| 15.38| 40.12| |LIDAR |7.58|7.05|9.23|6.86 |9.17|6.82|6.70|6.18|6.73|6.11|9.07|10.77|14.58|23.36| 1. I find the performance of camera based TTC estimation is depends on the combinations of detectors and descriptors. When the combination change, the performance will change a little. I think the reason is : the different detector and descriptor is suitable for different scenarios. Maybe in real world, we should implement a lots of combination and test them in each situation. According to the currrent situation, choose the right one. 2. For one combination of the detector and descriptors, the TTC estimation may be change not so stable from time to time. I think it may caused by the lightness/intensity change, or the object change in image (scale/rotation/affine transformation). 3. For camera TTC estimation, it can only compute the relative change in image. It can not measure the distance of the object. The TTC computation result is not so precise. Especially when the image change very fast, the TTC computation is not stable. The reason maybe the matching between two images is hard, when the image change a lot. So the estimation is not good.