├── LICENSE ├── Lane-Lines-Detection.ipynb ├── README.md ├── Writeup.md ├── _config.yml ├── output_example.jpg ├── output_videos ├── challenge_output.mp4 ├── solidWhiteRight_output.mp4 └── solidYellowLeft_output.mp4 ├── test_images ├── 01. solidWhiteCurve.jpg ├── 02. solidWhiteRight.jpg ├── 03. solidYellowCurve.jpg ├── 04. solidYellowCurve2.jpg ├── 05. solidYellowLeft.jpg ├── 06. whiteCarLaneSwitch.jpg ├── 07. VideoSnapshot2.jpg └── 09. VideoSnapshot3.jpg └── test_videos ├── challenge.mp4 ├── solidWhiteRight.mp4 └── solidYellowLeft.mp4 /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mohamed Ameen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **Lane Lines Detection Using Python and OpenCV** 2 | ### In this project, I used Python and OpenCV to detect lane lines on the road. I developed a processing pipeline that works on a series of individual images, and applied the result to a video stream. 3 | 4 | ![jpg](output_example.jpg) 5 | 6 | Pipeline architecture: 7 | --- 8 | 1. Load test images. 9 | 2. Apply Color Selection 10 | 3. Apply Canny edge detection. 11 | - Apply gray scaling to the images. 12 | - Apply Gaussian smoothing. 13 | - Perform Canny edge detection. 14 | 4. Determine the region of interest. 15 | 5. Apply Hough transform. 16 | 6. Average and extrapolating the lane lines. 17 | 7. Apply on video streams. 18 | 19 | I'll explain each step in details below. 20 | 21 | ## **Environement:** 22 | --- 23 | - Windows 7 24 | - Anaconda 4.3.29 25 | - Python 3.6.2 26 | - OpenCV 3.1.0 27 | 28 | ### **1. Loading test images:** 29 | ---- 30 | We have 6 test images. I wrote a function called `list_images()` that shows all the test images we're working on using matplotlib. 31 | 32 | ```python 33 | def list_images(images, cols = 2, rows = 5, cmap=None): 34 | """ 35 | Display a list of images in a single figure with matplotlib. 36 | Parameters: 37 | images: List of np.arrays compatible with plt.imshow. 38 | cols (Default = 2): Number of columns in the figure. 39 | rows (Default = 5): Number of rows in the figure. 40 | cmap (Default = None): Used to display gray images. 41 | """ 42 | plt.figure(figsize=(10, 11)) 43 | for i, image in enumerate(images): 44 | plt.subplot(rows, cols, i+1) 45 | #Use gray scale color map if there is only one channel 46 | cmap = 'gray' if len(image.shape) == 2 else cmap 47 | plt.imshow(image, cmap = cmap) 48 | plt.xticks([]) 49 | plt.yticks([]) 50 | plt.tight_layout(pad=0, h_pad=0, w_pad=0) 51 | plt.show() 52 | ``` 53 | 54 | ### **2. Color Selection:** 55 | ---- 56 | Lane lines in the test images are in white and yellow. We need to choose the most suitable color space, that clearly highlights the lane lines. 57 | I applied color selection to the original RGB images, HSV images, and HSL images, and found out that using HSL will be the best color space to use. 58 | 59 | ```python 60 | def HSL_color_selection(image): 61 | """ 62 | Apply color selection to the HSL images to blackout everything except for white and yellow lane lines. 63 | Parameters: 64 | image: An np.array compatible with plt.imshow. 65 | """ 66 | #Convert the input image to HSL 67 | converted_image = convert_hsl(image) 68 | 69 | #White color mask 70 | lower_threshold = np.uint8([0, 200, 0]) 71 | upper_threshold = np.uint8([255, 255, 255]) 72 | white_mask = cv2.inRange(converted_image, lower_threshold, upper_threshold) 73 | 74 | #Yellow color mask 75 | lower_threshold = np.uint8([10, 0, 100]) 76 | upper_threshold = np.uint8([40, 255, 255]) 77 | yellow_mask = cv2.inRange(converted_image, lower_threshold, upper_threshold) 78 | 79 | #Combine white and yellow masks 80 | mask = cv2.bitwise_or(white_mask, yellow_mask) 81 | masked_image = cv2.bitwise_and(image, image, mask = mask) 82 | 83 | return masked_image 84 | ``` 85 | 86 | ### **3. Canny Edge Detection** 87 | ---- 88 | We need to detect edges in the images to be able to correctly detect lane lines. 89 | The Canny edge detector is an edge detection operator that uses a multi-stage algorithm to detect a wide range of edges in images. 90 | The Canny algorithm involves the following steps: 91 | - Gray scaling the images: The Canny edge detection algorithm measures the intensity gradients of each pixel. So, we need to convert the images into gray scale in order to detect edges. 92 | - Gaussian smoothing: Since all edge detection results are easily affected by image noise, it is essential to filter out the noise to prevent false detection caused by noise. To smooth the image, a Gaussian filter is applied to convolve with the image. This step will slightly smooth the image to reduce the effects of obvious noise on the edge detector. 93 | - Find the intensity gradients of the image. 94 | - Apply non-maximum suppression to get rid of spurious response to edge detection. 95 | - Apply double threshold to determine potential edges. 96 | - Track edge by hysteresis: Finalize the detection of edges by suppressing all the other edges that are weak and not connected to strong edges. 97 | If an edge pixel’s gradient value is higher than the high threshold value, it is marked as a strong edge pixel. If an edge pixel’s gradient value is smaller than the high threshold value and larger than the low threshold value, it is marked as a weak edge pixel. If an edge pixel's value is smaller than the low threshold value, it will be suppressed. The two threshold values are empirically determined and their definition will depend on the content of a given input image. 98 | 99 | ### **4. Region of interest** 100 | ---- 101 | We're interested in the area facing the camera, where the lane lines are found. So, we'll apply region masking to cut out everything else. 102 | 103 | ```python 104 | def region_selection(image): 105 | """ 106 | Determine and cut the region of interest in the input image. 107 | Parameters: 108 | image: An np.array compatible with plt.imshow. 109 | """ 110 | mask = np.zeros_like(image) 111 | #Defining a 3 channel or 1 channel color to fill the mask with depending on the input image 112 | if len(image.shape) > 2: 113 | channel_count = image.shape[2] 114 | ignore_mask_color = (255,) * channel_count 115 | else: 116 | ignore_mask_color = 255 117 | #We could have used fixed numbers as the vertices of the polygon, 118 | #but they will not be applicable to images with different dimesnions. 119 | rows, cols = image.shape[:2] 120 | bottom_left = [cols * 0.1, rows * 0.95] 121 | top_left = [cols * 0.4, rows * 0.6] 122 | bottom_right = [cols * 0.9, rows * 0.95] 123 | top_right = [cols * 0.6, rows * 0.6] 124 | vertices = np.array([[bottom_left, top_left, top_right, bottom_right]], dtype=np.int32) 125 | cv2.fillPoly(mask, vertices, ignore_mask_color) 126 | masked_image = cv2.bitwise_and(image, mask) 127 | return masked_image 128 | ``` 129 | 130 | ### **5. Hough Transform** 131 | ---- 132 | The Hough transform is a technique which can be used to isolate features of a particular shape within an image. I'll use it to detected the lane lines in `selected_region_images`. 133 | 134 | ```python 135 | def hough_transform(image): 136 | """ 137 | Determine and cut the region of interest in the input image. 138 | Parameters: 139 | image: The output of a Canny transform. 140 | """ 141 | rho = 1 #Distance resolution of the accumulator in pixels. 142 | theta = np.pi/180 #Angle resolution of the accumulator in radians. 143 | threshold = 20 #Only lines that are greater than threshold will be returned. 144 | minLineLength = 20 #Line segments shorter than that are rejected. 145 | maxLineGap = 300 #Maximum allowed gap between points on the same line to link them 146 | return cv2.HoughLinesP(image, rho = rho, theta = theta, threshold = threshold, 147 | minLineLength = minLineLength, maxLineGap = maxLineGap) 148 | ``` 149 | 150 | ### **6. Averaging and extrapolating the lane lines** 151 | ---- 152 | We have multiple lines detected for each lane line. We need to average all these lines and draw a single line for each lane line. We also need to extrapolate the lane lines to cover the full lane line length. 153 | ```python 154 | def average_slope_intercept(lines): 155 | """ 156 | Find the slope and intercept of the left and right lanes of each image. 157 | Parameters: 158 | lines: The output lines from Hough Transform. 159 | """ 160 | left_lines = [] #(slope, intercept) 161 | left_weights = [] #(length,) 162 | right_lines = [] #(slope, intercept) 163 | right_weights = [] #(length,) 164 | 165 | for line in lines: 166 | for x1, y1, x2, y2 in line: 167 | if x1 == x2: 168 | continue 169 | slope = (y2 - y1) / (x2 - x1) 170 | intercept = y1 - (slope * x1) 171 | length = np.sqrt(((y2 - y1) ** 2) + ((x2 - x1) ** 2)) 172 | if slope < 0: 173 | left_lines.append((slope, intercept)) 174 | left_weights.append((length)) 175 | else: 176 | right_lines.append((slope, intercept)) 177 | right_weights.append((length)) 178 | left_lane = np.dot(left_weights, left_lines) / np.sum(left_weights) if len(left_weights) > 0 else None 179 | right_lane = np.dot(right_weights, right_lines) / np.sum(right_weights) if len(right_weights) > 0 else None 180 | return left_lane, right_lane 181 | 182 | def pixel_points(y1, y2, line): 183 | """ 184 | Converts the slope and intercept of each line into pixel points. 185 | Parameters: 186 | y1: y-value of the line's starting point. 187 | y2: y-value of the line's end point. 188 | line: The slope and intercept of the line. 189 | """ 190 | if line is None: 191 | return None 192 | slope, intercept = line 193 | x1 = int((y1 - intercept)/slope) 194 | x2 = int((y2 - intercept)/slope) 195 | y1 = int(y1) 196 | y2 = int(y2) 197 | return ((x1, y1), (x2, y2)) 198 | 199 | def lane_lines(image, lines): 200 | """ 201 | Create full lenght lines from pixel points. 202 | Parameters: 203 | image: The input test image. 204 | lines: The output lines from Hough Transform. 205 | """ 206 | left_lane, right_lane = average_slope_intercept(lines) 207 | y1 = image.shape[0] 208 | y2 = y1 * 0.6 209 | left_line = pixel_points(y1, y2, left_lane) 210 | right_line = pixel_points(y1, y2, right_lane) 211 | return left_line, right_line 212 | 213 | def draw_lane_lines(image, lines, color=[255, 0, 0], thickness=12): 214 | """ 215 | Draw lines onto the input image. 216 | Parameters: 217 | image: The input test image. 218 | lines: The output lines from Hough Transform. 219 | color (Default = red): Line color. 220 | thickness (Default = 12): Line thickness. 221 | """ 222 | line_image = np.zeros_like(image) 223 | for line in lines: 224 | if line is not None: 225 | cv2.line(line_image, *line, color, thickness) 226 | return cv2.addWeighted(image, 1.0, line_image, 1.0, 0.0) 227 | ``` 228 | 229 | 230 | ### **7. Apply on video streams** 231 | ---- 232 | Now, we'll use the above functions to detect lane lines from a video stream. 233 | The video inputs are in test_videos folder. The video outputs are generated in output_videos folder. 234 | 235 | ```python 236 | def frame_processor(image): 237 | """ 238 | Process the input frame to detect lane lines. 239 | Parameters: 240 | image: Single video frame. 241 | """ 242 | color_select = HSL_color_selection(image) 243 | gray = gray_scale(color_select) 244 | smooth = gaussian_smoothing(gray) 245 | edges = canny_detector(smooth) 246 | region = region_selection(edges) 247 | hough = hough_transform(region) 248 | result = draw_lane_lines(image, lane_lines(image, hough)) 249 | return result 250 | 251 | def process_video(test_video, output_video): 252 | """ 253 | Read input video stream and produce a video file with detected lane lines. 254 | Parameters: 255 | test_video: Input video. 256 | output_video: A video file with detected lane lines. 257 | """ 258 | input_video = VideoFileClip(os.path.join('test_videos', test_video), audio=False) 259 | processed = input_video.fl_image(frame_processor) 260 | processed.write_videofile(os.path.join('output_videos', output_video), audio=False) 261 | ``` 262 | 263 | ## **Conclusion:** 264 | ---- 265 | The project succeeded in detecting the lane lines clearly in the video streams. 266 | This project is intended to only detect (mostly) straight lines. Detecting curved lane line is behind the scope of this work. 267 | -------------------------------------------------------------------------------- /Writeup.md: -------------------------------------------------------------------------------- 1 | # **Lane Lines Detection Using Python and OpenCV** 2 | ### In this project, I used Python and OpenCV to detect lane lines on the road. I developed a processing pipeline that works on a series of individual images, and applied the result to a video stream. 3 | 4 | ![jpg](output_example.jpg) 5 | 6 | Pipeline architecture: 7 | --- 8 | 1. Load test images. 9 | 2. Apply Color Selection 10 | 3. Apply Canny edge detection. 11 | - Apply gray scaling to the images. 12 | - Apply Gaussian smoothing. 13 | - Perform Canny edge detection. 14 | 4. Determine the region of interest. 15 | 5. Apply Hough transform. 16 | 6. Average and extrapolating the lane lines. 17 | 7. Apply on video streams. 18 | 19 | 20 | ### **1. Loading test images:** 21 | ---- 22 | We have 6 test images. I wrote a function called `list_images()` that shows all the test images we're working on using matplotlib. 23 | 24 | ```python 25 | def list_images(images, cols = 2, rows = 5, cmap=None): 26 | """ 27 | Display a list of images in a single figure with matplotlib. 28 | Parameters: 29 | images: List of np.arrays compatible with plt.imshow. 30 | cols (Default = 2): Number of columns in the figure. 31 | rows (Default = 5): Number of rows in the figure. 32 | cmap (Default = None): Used to display gray images. 33 | """ 34 | plt.figure(figsize=(10, 11)) 35 | for i, image in enumerate(images): 36 | plt.subplot(rows, cols, i+1) 37 | #Use gray scale color map if there is only one channel 38 | cmap = 'gray' if len(image.shape) == 2 else cmap 39 | plt.imshow(image, cmap = cmap) 40 | plt.xticks([]) 41 | plt.yticks([]) 42 | plt.tight_layout(pad=0, h_pad=0, w_pad=0) 43 | plt.show() 44 | ``` 45 | 46 | ### **2. Color Selection:** 47 | ---- 48 | Lane lines in the test images are in white and yellow. We need to choose the most suitable color space, that clearly highlights the lane lines. 49 | I applied color selection to the original RGB images, HSV images, and HSL images, and found out that using HSL will be the best color space to use. 50 | 51 | ```python 52 | def HSL_color_selection(image): 53 | """ 54 | Apply color selection to the HSL images to blackout everything except for white and yellow lane lines. 55 | Parameters: 56 | image: An np.array compatible with plt.imshow. 57 | """ 58 | #Convert the input image to HSL 59 | converted_image = convert_hsl(image) 60 | 61 | #White color mask 62 | lower_threshold = np.uint8([0, 200, 0]) 63 | upper_threshold = np.uint8([255, 255, 255]) 64 | white_mask = cv2.inRange(converted_image, lower_threshold, upper_threshold) 65 | 66 | #Yellow color mask 67 | lower_threshold = np.uint8([10, 0, 100]) 68 | upper_threshold = np.uint8([40, 255, 255]) 69 | yellow_mask = cv2.inRange(converted_image, lower_threshold, upper_threshold) 70 | 71 | #Combine white and yellow masks 72 | mask = cv2.bitwise_or(white_mask, yellow_mask) 73 | masked_image = cv2.bitwise_and(image, image, mask = mask) 74 | 75 | return masked_image 76 | ``` 77 | 78 | ### **3. Canny Edge Detection** 79 | ---- 80 | We need to detect edges in the images to be able to correctly detect lane lines. 81 | The Canny edge detector is an edge detection operator that uses a multi-stage algorithm to detect a wide range of edges in images. 82 | The Canny algorithm involves the following steps: 83 | - Gray scaling the images: The Canny edge detection algorithm measures the intensity gradients of each pixel. So, we need to convert the images into gray scale in order to detect edges. 84 | - Gaussian smoothing: Since all edge detection results are easily affected by image noise, it is essential to filter out the noise to prevent false detection caused by noise. To smooth the image, a Gaussian filter is applied to convolve with the image. This step will slightly smooth the image to reduce the effects of obvious noise on the edge detector. 85 | - Find the intensity gradients of the image. 86 | - Apply non-maximum suppression to get rid of spurious response to edge detection. 87 | - Apply double threshold to determine potential edges. 88 | - Track edge by hysteresis: Finalize the detection of edges by suppressing all the other edges that are weak and not connected to strong edges. 89 | If an edge pixel’s gradient value is higher than the high threshold value, it is marked as a strong edge pixel. If an edge pixel’s gradient value is smaller than the high threshold value and larger than the low threshold value, it is marked as a weak edge pixel. If an edge pixel's value is smaller than the low threshold value, it will be suppressed. The two threshold values are empirically determined and their definition will depend on the content of a given input image. 90 | 91 | ### **4. Region of interest** 92 | ---- 93 | We're interested in the area facing the camera, where the lane lines are found. So, we'll apply region masking to cut out everything else. 94 | 95 | ```python 96 | def region_selection(image): 97 | """ 98 | Determine and cut the region of interest in the input image. 99 | Parameters: 100 | image: An np.array compatible with plt.imshow. 101 | """ 102 | mask = np.zeros_like(image) 103 | #Defining a 3 channel or 1 channel color to fill the mask with depending on the input image 104 | if len(image.shape) > 2: 105 | channel_count = image.shape[2] 106 | ignore_mask_color = (255,) * channel_count 107 | else: 108 | ignore_mask_color = 255 109 | #We could have used fixed numbers as the vertices of the polygon, 110 | #but they will not be applicable to images with different dimesnions. 111 | rows, cols = image.shape[:2] 112 | bottom_left = [cols * 0.1, rows * 0.95] 113 | top_left = [cols * 0.4, rows * 0.6] 114 | bottom_right = [cols * 0.9, rows * 0.95] 115 | top_right = [cols * 0.6, rows * 0.6] 116 | vertices = np.array([[bottom_left, top_left, top_right, bottom_right]], dtype=np.int32) 117 | cv2.fillPoly(mask, vertices, ignore_mask_color) 118 | masked_image = cv2.bitwise_and(image, mask) 119 | return masked_image 120 | ``` 121 | 122 | ### **5. Hough Transform** 123 | ---- 124 | The Hough transform is a technique which can be used to isolate features of a particular shape within an image. I'll use it to detected the lane lines in `selected_region_images`. 125 | 126 | ```python 127 | def hough_transform(image): 128 | """ 129 | Determine and cut the region of interest in the input image. 130 | Parameters: 131 | image: The output of a Canny transform. 132 | """ 133 | rho = 1 #Distance resolution of the accumulator in pixels. 134 | theta = np.pi/180 #Angle resolution of the accumulator in radians. 135 | threshold = 20 #Only lines that are greater than threshold will be returned. 136 | minLineLength = 20 #Line segments shorter than that are rejected. 137 | maxLineGap = 300 #Maximum allowed gap between points on the same line to link them 138 | return cv2.HoughLinesP(image, rho = rho, theta = theta, threshold = threshold, 139 | minLineLength = minLineLength, maxLineGap = maxLineGap) 140 | ``` 141 | 142 | ### **6. Averaging and extrapolating the lane lines** 143 | ---- 144 | We have multiple lines detected for each lane line. We need to average all these lines and draw a single line for each lane line. 145 | We also need to extrapolate the lane lines to cover the full lane line length. 146 | 147 | The left lane should have a negative slope (given that `y` coordinate is reversed in the images), and the right lane should have a negative slope. Therefore, we'll collect positive slope lines and negative slope lines separately and take averages. 148 | After calculating the average slope and intercept of each lane line, we'll convert these values to pixel points, and then we'll be able to draw the full length lane line. 149 | 150 | ```python 151 | def average_slope_intercept(lines): 152 | """ 153 | Find the slope and intercept of the left and right lanes of each image. 154 | Parameters: 155 | lines: The output lines from Hough Transform. 156 | """ 157 | left_lines = [] #(slope, intercept) 158 | left_weights = [] #(length,) 159 | right_lines = [] #(slope, intercept) 160 | right_weights = [] #(length,) 161 | 162 | for line in lines: 163 | for x1, y1, x2, y2 in line: 164 | if x1 == x2: 165 | continue 166 | slope = (y2 - y1) / (x2 - x1) 167 | intercept = y1 - (slope * x1) 168 | length = np.sqrt(((y2 - y1) ** 2) + ((x2 - x1) ** 2)) 169 | if slope < 0: 170 | left_lines.append((slope, intercept)) 171 | left_weights.append((length)) 172 | else: 173 | right_lines.append((slope, intercept)) 174 | right_weights.append((length)) 175 | left_lane = np.dot(left_weights, left_lines) / np.sum(left_weights) if len(left_weights) > 0 else None 176 | right_lane = np.dot(right_weights, right_lines) / np.sum(right_weights) if len(right_weights) > 0 else None 177 | return left_lane, right_lane 178 | 179 | def pixel_points(y1, y2, line): 180 | """ 181 | Converts the slope and intercept of each line into pixel points. 182 | Parameters: 183 | y1: y-value of the line's starting point. 184 | y2: y-value of the line's end point. 185 | line: The slope and intercept of the line. 186 | """ 187 | if line is None: 188 | return None 189 | slope, intercept = line 190 | x1 = int((y1 - intercept)/slope) 191 | x2 = int((y2 - intercept)/slope) 192 | y1 = int(y1) 193 | y2 = int(y2) 194 | return ((x1, y1), (x2, y2)) 195 | 196 | def lane_lines(image, lines): 197 | """ 198 | Create full lenght lines from pixel points. 199 | Parameters: 200 | image: The input test image. 201 | lines: The output lines from Hough Transform. 202 | """ 203 | left_lane, right_lane = average_slope_intercept(lines) 204 | y1 = image.shape[0] 205 | y2 = y1 * 0.6 206 | left_line = pixel_points(y1, y2, left_lane) 207 | right_line = pixel_points(y1, y2, right_lane) 208 | return left_line, right_line 209 | 210 | def draw_lane_lines(image, lines, color=[255, 0, 0], thickness=12): 211 | """ 212 | Draw lines onto the input image. 213 | Parameters: 214 | image: The input test image. 215 | lines: The output lines from Hough Transform. 216 | color (Default = red): Line color. 217 | thickness (Default = 12): Line thickness. 218 | """ 219 | line_image = np.zeros_like(image) 220 | for line in lines: 221 | if line is not None: 222 | cv2.line(line_image, *line, color, thickness) 223 | return cv2.addWeighted(image, 1.0, line_image, 1.0, 0.0) 224 | ``` 225 | 226 | 227 | ### **7. Apply on video streams** 228 | ---- 229 | Now, we'll use the above functions to detect lane lines from a video stream. 230 | The video inputs are in test_videos folder. The video outputs are generated in output_videos folder. 231 | 232 | ```python 233 | def frame_processor(image): 234 | """ 235 | Process the input frame to detect lane lines. 236 | Parameters: 237 | image: Single video frame. 238 | """ 239 | color_select = HSL_color_selection(image) 240 | gray = gray_scale(color_select) 241 | smooth = gaussian_smoothing(gray) 242 | edges = canny_detector(smooth) 243 | region = region_selection(edges) 244 | hough = hough_transform(region) 245 | result = draw_lane_lines(image, lane_lines(image, hough)) 246 | return result 247 | 248 | def process_video(test_video, output_video): 249 | """ 250 | Read input video stream and produce a video file with detected lane lines. 251 | Parameters: 252 | test_video: Input video. 253 | output_video: A video file with detected lane lines. 254 | """ 255 | input_video = VideoFileClip(os.path.join('test_videos', test_video), audio=False) 256 | processed = input_video.fl_image(frame_processor) 257 | processed.write_videofile(os.path.join('output_videos', output_video), audio=False) 258 | ``` 259 | 260 | ## **Conclusion:** 261 | ---- 262 | The project succeeded in detecting the lane lines clearly in the video streams. 263 | This project is intended to only detect (mostly) straight lines. A possible improvement would be to modify the above pipeline to detect curved lane line. 264 | Another potential improvement could be to identify the lane boundaries and detect the full lane, not just the lane lines. -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /output_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/output_example.jpg -------------------------------------------------------------------------------- /output_videos/challenge_output.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/output_videos/challenge_output.mp4 -------------------------------------------------------------------------------- /output_videos/solidWhiteRight_output.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/output_videos/solidWhiteRight_output.mp4 -------------------------------------------------------------------------------- /output_videos/solidYellowLeft_output.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/output_videos/solidYellowLeft_output.mp4 -------------------------------------------------------------------------------- /test_images/01. solidWhiteCurve.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/01. solidWhiteCurve.jpg -------------------------------------------------------------------------------- /test_images/02. solidWhiteRight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/02. solidWhiteRight.jpg -------------------------------------------------------------------------------- /test_images/03. solidYellowCurve.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/03. solidYellowCurve.jpg -------------------------------------------------------------------------------- /test_images/04. solidYellowCurve2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/04. solidYellowCurve2.jpg -------------------------------------------------------------------------------- /test_images/05. solidYellowLeft.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/05. solidYellowLeft.jpg -------------------------------------------------------------------------------- /test_images/06. whiteCarLaneSwitch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/06. whiteCarLaneSwitch.jpg -------------------------------------------------------------------------------- /test_images/07. VideoSnapshot2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/07. VideoSnapshot2.jpg -------------------------------------------------------------------------------- /test_images/09. VideoSnapshot3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_images/09. VideoSnapshot3.jpg -------------------------------------------------------------------------------- /test_videos/challenge.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_videos/challenge.mp4 -------------------------------------------------------------------------------- /test_videos/solidWhiteRight.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_videos/solidWhiteRight.mp4 -------------------------------------------------------------------------------- /test_videos/solidYellowLeft.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohamedameen93/Lane-lines-detection-using-Python-and-OpenCV/2021c8e398240e1433e6982a68b0f4774eef3600/test_videos/solidYellowLeft.mp4 --------------------------------------------------------------------------------