import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np import cv2 import math import os def grayscale(img): # It converts the original picture to the gray scale picture. """Applies the Grayscale transform This will return an image with only one color channel but NOTE: to see the returned image as grayscale (assuming your grayscaled image is called 'gray') you should call plt.imshow(gray, cmap='gray')""" return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # Or use BGR2GRAY if you read an image with cv2.imread() # return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) def canny(img, low_threshold, high_threshold): #After applied grayscale function, it converts the grayscale image to edges #which is a binary image with white pixels. """Applies the Canny transform""" return cv2.Canny(img, low_threshold, high_threshold) def gaussian_blur(img, kernel_size): #Gaussian blur is applied for suppressing noise and nonlogical gradients by averaging. """Applies a Gaussian Noise kernel""" return cv2.GaussianBlur(img, (kernel_size, kernel_size), 0) def region_of_interest(img, vertices): # This functions is used for tracing a specific line of the road # utilizing vertices which is are 4 integer points here and ignore_mask_color which ignores # pixels if those do not meet the criteria. """ Applies an image mask. Only keeps the region of the image defined by the polygon formed from `vertices`. The rest of the image is set to black. `vertices` should be a numpy array of integer points. """ #defining a blank mask to start with mask = np.zeros_like(img) #defining a 3 channel or 1 channel color to fill the mask with depending on the input image if len(img.shape) > 2: channel_count = img.shape[2] # i.e. 3 or 4 depending on your image ignore_mask_color = (255,) * channel_count else: ignore_mask_color = 255 #filling pixels inside the polygon defined by "vertices" with the fill color cv2.fillPoly(mask, vertices, ignore_mask_color) #returning the image only where mask pixels are nonzero masked_image = cv2.bitwise_and(img, mask) return masked_image def draw_lines(img, lines, color=[255, 0, 0], thickness=2): """ NOTE: this is the function you might want to use as a starting point once you want to average/extrapolate the line segments you detect to map out the full extent of the lane (going from the result shown in raw-lines-example.mp4 to that shown in P1_example.mp4). Think about things like separating line segments by their slope ((y2-y1)/(x2-x1)) to decide which segments are part of the left line vs. the right line. Then, you can average the position of each of the lines and extrapolate to the top and bottom of the lane. This function draws `lines` with `color` and `thickness`. Lines are drawn on the image inplace (mutates the image). If you want to make the lines semi-transparent, think about combining this function with the weighted_img() function below """ """ for line in lines: for x1,y1,x2,y2 in line: cv2.line(img, (x1, y1), (x2, y2), color, thickness) """ right_slopes = [] right_intercepts = [] left_slopes = [] left_intercepts = [] left_points_x = [] left_points_y = [] right_points_x = [] right_points_y = [] y_max = img.shape[0] y_min = img.shape[0] for line in lines: for x1,y1,x2,y2 in line: slope = (y2-y1)/(x2-x1) if slope < 0.0 and slope > -math.inf: # math.inf = floating point positive infinity left_slopes.append(slope) # left line left_points_x.append(x1) left_points_x.append(x2) left_points_y.append(y1) left_points_y.append(y2) left_intercepts.append(y1 - slope*x1) if slope > 0.0 and slope < math.inf: right_slopes.append(slope) # right line right_points_x.append(x1) right_points_x.append(x2) right_points_y.append(y1) right_points_y.append(y2) right_intercepts.append(y1 - slope*x1) y_min = min(y1,y2,y_min) if len(left_slopes) > 0: left_slope = np.mean(left_slopes) left_intercept = np.mean(left_intercepts) x_min_left = int((y_min - left_intercept)/left_slope) x_max_left = int((y_max - left_intercept)/left_slope) cv2.line(img, (x_min_left, y_min), (x_max_left, y_max), [255, 0, 0], 8) if len(right_slopes) > 0: right_slope = np.mean(right_slopes) right_intercept = np.mean(right_intercepts) x_min_right = int((y_min - right_intercept)/right_slope) x_max_right = int((y_max - right_intercept)/right_slope) cv2.line(img, (x_min_right, y_min), (x_max_right, y_max), [255, 0, 0], 8) def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap): #This function is used for drawing line when we give a specific criteria into the pixels we want to pick up. #This function is used with draw_lines function to draw the lines in specific pixels #which are drawn by region_of_interest function. """ `img` should be the output of a Canny transform. Returns an image with hough lines drawn. """ lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]), minLineLength=min_line_len, maxLineGap=max_line_gap) line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8) draw_lines(line_img, lines) return line_img # Python 3 has support for cool math symbols. def weighted_img(img, initial_img, α=0.8, β=1., γ=0.): # By appliying "color" binary image, it finally draws the line on the edge image. """ `img` is the output of the hough_lines(), An image with lines drawn on it. Should be a blank image (all black) with lines drawn on it. `initial_img` should be the image before any processing. The result image is computed as follows: initial_img * α + img * β + γ NOTE: initial_img and img must be the same shape! """ return cv2.addWeighted(initial_img, α, img, β, γ) def process_image(image): # NOTE: The output you return should be a color image (3 channel) for processing video below # TODO: put your pipeline here, # you should return the final output (image where lines are drawn on lanes) # Read in and grayscale the image gray = grayscale(image) # Define a kernel size and apply Gaussian smoothing kernel_size = 5 blur_gray = gaussian_blur(gray, kernel_size) # Define our parameters for Canny and apply low_threshold = 50 high_threshold = 150 edges = canny(blur_gray, low_threshold, high_threshold) # Next we'll create a masked edges image using cv2.fillPoly() imshape = image.shape vertices = np.array([[(120,imshape[0]),(450, 320), (500, 320), (imshape[1],imshape[0])]], dtype=np.int32) masked_edges = region_of_interest(edges, vertices) # Define the Hough transform parameters # Make a blank the same size as our image to draw on rho = 2 # distance resolution in pixels of the Hough grid theta = np.pi/180 # angular resolution in radians of the Hough grid threshold = 15 # minimum number of votes (intersections in Hough grid cell) min_line_len = 40 # minimum number of pixels making up a line max_line_gap = 20 # maximum gap in pixels between connectable line segments line_image = np.copy(image)*1 #creating a blank to draw lines on # Run Hough on edge detected image lines = hough_lines(masked_edges, rho, theta, threshold, min_line_len, max_line_gap) # Create a "color" binary image to combine with line image color_edges = np.dstack((edges, edges, edges)) # Draw the lines on the edge image lines_edges = weighted_img(lines, line_image) return lines_edges
来自:https://stackoverflow.com/