joustava / CarND-AdvancedLaneFinding-P2

Second project of the Udacity, Self-Driving Car Engineer, course

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Advanced Lane Finding Project

Python project to explore the topic of advanced lane finding. This project is created as one possible solution to the second project of Udacity's Nano Degree Self Driving Car Engineer in the School of Autonomous Systems.

Goal

The goals / steps of this project are the following:

  • Compute the camera calibration matrix and distortion coefficients given a set of chessboard images.
  • Apply a distortion correction to raw images.
  • Use color transforms, gradients, etc., to create a thresholded binary image.
  • Apply a perspective transform to rectify binary image ("birds-eye view").
  • Detect lane pixels and fit to find the lane boundary.
  • Determine the curvature of the lane and vehicle position with respect to center.
  • Warp the detected lane boundaries back onto the original image.
  • Output visual display of the lane boundaries and numerical estimation of lane curvature and vehicle position.

A full project rubrick can be found from the project specification (when logged in to Udacity).

Setup

This work has been created with the help of Docker in order to keep your local environment clean and for easy execution of the pipeline. When Docker is installed, running make run from the repo root directory will start the Docker container and run the pipeline. Output from the pipeline will end up into the assets/output_images directory.

The images for camera calibration are stored in the folder called assets/camera_cal. The images in assets/test_images are for testing the pipeline on single frames.

Read more about the setup


1. Camera Calibration

The code for this step is contained in the class DistortionCorrector found in alf/pipeline/distortion_corrector.py.
Before using the DistortionCorrector it needs to be calibrated by passing a set of images to its calibrate method. For each valid calibration image, its corners are found and stored to a collection. At the same time a collection is updated with the point indexes.

Once all the calibration data is collected, an image can be undistorted by using the undistort method form the same DistortionCorrector object. An example is shown in the table below:

Input Output
Example of distorted calibration image Example of undistorted calibration image

2. Pipeline (single images)

2.1 Distortion correction

Once we have a calibrated DistortionCorrector object as described in section 1.1. we can simply apply the undistort method on any of our test images found from the ./assets/test_images directory. The effect can be seen from the table below.

Input Output
Example of distorted test image Example of undistorted test image

As the calibration step can take some time, we should make sure the DistortionCorrector is calibrated only once during the pipeline processing.

2.2 Binary Threshold

With a ImageThresholder object, created from its class found in ./src/alf/pipeline/thresholder.py, both color and gradient thresholds are applied to an image in the threshold() function. This function combines the threshold results as a binary image. The table below shows input, gradient thresholded, color thresholded and both threshold combined.

Input gradient threshold
Example of undistorted test image Example of gradient thresholded image
color threshold combined thresholds
Example of color thresholded image Example of combined threshold image

2.3 Perspective Transform

The perspective transform requires the knowledge of a set of source points which then are mapped onto desired destination points. We will find them manually for now but trying to find both sets automatically seems a good usecase for reusing code from lane finding project.

The source and destination points are created in the Roi class found in alf/common/roi.py. For the source points I chose values that created a snug fit on the outsides of the lane when plotted on the .assets/test_images/straight_lines2 image. The desination points are based on the source points whereby the upper point position are changed so that the resulting polygon becomes a square. This resulted in the following source and destination points:

SRC points DST points
602, 444 305, 0
680, 444 1020, 0
1120, 720 1020, 720
205, 720 305, 720

I verified that my perspective transform was working as expected by drawing the src points onto a test image and then inspect that the perspective transformed counterpart contained the points in a rectangular fashion.

Input Source points (marked) Warped (marked)
Example of selection image Example of source points selection image Example of binary image

The images contain the points and lines for illustrative purposed, they will not be drawn in the actual pipeline. It seems that the transform is succesful as the bounding box is a rectangle and the lane lines can be considered to be perpendicular to each other as in the original picture.

2.4. Polynomial fitting of lane lines

First, from the perspective transformed binary lane frame the line x positions are found with the help a histogram. Then an amount of sliding windows (green) are placed iteratively over the lane pixels from bottom to top. The pixel indices (x and y values) are then used to fit a polynomial (yellow).

Input Windowed Search
Example of warped binary image Example of windowed search

From the data found the left and right lines are drawn and the lane itself is filled. This visualisation is then perspective transformed back into the original frame perspective.

Lane visualisation Original perspective
Example of Lane visualisation Example of original perspective

2.5. Radius of curvature of the lane and vehicle position with respect to center

-- TBD

2.6. Lane area visualization

The lane visualisation is taken care of within the alf/processor.py file. A copy of the perspective transformed lanes with polylines and windows is resized and placed within the end result of the pipeline.

Lane visualization


3. Pipeline (video)

Here's a link to my video result


Discussion

The current pipeline works good enough for the first video, it is stable enough during the whole lenght. Due to the lane length chosen the upper bounds of the lines are not detected in a precise manner as they move out of their measured pixel space (left vs right halves of frame).

Improvements such as masking, keeping a running average and use that when data is missing from a few sequential frames would improve the algorithm.

Sources

About

Second project of the Udacity, Self-Driving Car Engineer, course

License:Other


Languages

Language:HTML 87.1%Language:Python 12.2%Language:Makefile 0.5%Language:Dockerfile 0.3%