def debug_test_img(self): img = cv2.imread("./camera_cal/calibration1.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = self.undistort(gray) DEBUG.save_img(gray, "test_undistorted_calibration0.jpg") img = cv2.imread("./test_images/test1.jpg") img = self.undistort(img) DEBUG.save_img(img, "test_undistorted_test1.jpg")
def progressive_binary(saturation_warped, grayscale_warped, saturation_warped_threshold): # I think I'm supposed to be applying the threshold on the raw saturation value #raise Exception("I'm not certain I'm even supposed to be applying sobel on top of the saturation value.") # Sobel kernel of 3 for bottom half sobel_kernel = 3 sobelx_kernel_3_s = cv2.Sobel(saturation_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) sobelx_kernel_3_gray = cv2.Sobel(grayscale_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) # right now, no matter what i do I can't find the top mark in the test2 sobel_kernel = 5 sobelx_kernel_5_s = cv2.Sobel(saturation_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) sobelx_kernel_5_gray = cv2.Sobel(grayscale_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) DEBUG.save_img(grayscale_warped, "gray.png") DEBUG.save_img(sobelx_kernel_5_gray, "saturatsobelx_kernel_5_gray.png") DEBUG.save_img(sobelx_kernel_3_gray, "sobelx_kernel_3_gray.png") #sobel_kernel = 9 #sobelx_kernel_9_s = cv2.Sobel(saturation_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) #sobelx_kernel_9_gray = cv2.Sobel(grayscale_warped, cv2.CV_64F, 1, 0, ksize=sobel_kernel) # TODO: don't just use the saturation binary. Also use the grayscale one. # the two of them are better toghether. # https://classroom.udacity.com/nanodegrees/nd013/parts/fbf77062-5703-404e-b60c-95b78b2f3f9e/modules/2b62a1c3-e151-4a0e-b6b6-e424fa46ceab/lessons/0bcd97c5-66f3-495b-9fe2-3f9f541bae25/concepts/a1b70df9-638b-46bb-8af0-12c43dcfd0b4 # bottom_half = img[img.shape[0]//2:,:] height = saturation_warped.shape[0] binary_sobelx = np.zeros_like(saturation_warped) apply_filter(sobelx_kernel_3_s, sobelx_kernel_3_gray, height//2, height, binary_sobelx, 30, 50) apply_filter(sobelx_kernel_3_s, sobelx_kernel_5_gray, height//4, height//2, binary_sobelx, 20, 100) apply_filter(sobelx_kernel_3_s, sobelx_kernel_5_gray, 0, height//4, binary_sobelx, 20, 500) return binary_sobelx
def process_img(img, name): # # WARP TO NEW PERSPECTIVE # source_points = get_image_points() img = camera.undistort(img) DEBUG.save_img_with_path(img, source_points, name) source_points = np.array(source_points, np.float32) destination_points = np.array(get_destination_points(), np.float32) M = cv2.getPerspectiveTransform(source_points, destination_points) warped = cv2.warpPerspective(img, M, camera.viewport_size(), flags=cv2.INTER_LINEAR) DEBUG.save_img(warped, "warped_" + name) # # CREATE BINARY IMAGE # # Create grayscale image grayscale_warped = cv2.cvtColor(warped, cv2.COLOR_RGB2GRAY) hls_warped = cv2.cvtColor(warped, cv2.COLOR_RGB2HLS) saturation_warped = hls_warped[:,:,2] l_warped = hls_warped[:,:,1] #DEBUG.save_img(saturation_warped, "warped_saturation_" + name) saturation_warped_threshold = np.zeros_like(saturation_warped) # edge detection on a combination of saturation and grayscale. # saturation is mostly useful on yellow. So this is our best bet. binary_sobelx = progressive_binary(saturation_warped, grayscale_warped, saturation_warped_threshold) #DEBUG.save_img(binary_sobelx, "binary_" + name) # find the peaks in the bottom half of the image. This is the starting # point for finding the lane. histogram = bottom_half_histogram(binary_sobelx) max_first_half = histogram[:len(histogram)//2].argmax() max_second_half = histogram[len(histogram)//2:].argmax() + len(histogram)//2 annotated_image, left_path = find_lines(max_first_half, binary_sobelx) #DEBUG.save_img(annotated_image, "annotated_output_left_" + name + ".png") annotated_image, right_path = find_lines(max_second_half, binary_sobelx) #DEBUG.save_img(annotated_image, "annotated_output_right_" + name + ".png") # # Fit polylines to the detected lane points # # Generate x and y values for plotting in projected space fit_poly_left = np.polyfit([x[1] for x in left_path], [x[0] for x in left_path], 2) fit_poly_right = np.polyfit([x[1] for x in right_path], [x[0] for x in right_path], 2) ploty = np.linspace(0, binary_sobelx.shape[0]-1, binary_sobelx.shape[0]) left_fitx = fit_poly_left[0]*ploty**2 + fit_poly_left[1]*ploty + fit_poly_left[2] right_fitx = fit_poly_right[0]*ploty**2 + fit_poly_right[1]*ploty + fit_poly_right[2] # Convert left path back to original space path_left = list(zip(left_fitx, ploty)) path_left = np.array([(path_left)], dtype=np.float32) reverse_transform = cv2.getPerspectiveTransform(destination_points, source_points) converted_left_path = cv2.perspectiveTransform(path_left, reverse_transform) # Convert right path back to original space path_right = list(zip(right_fitx, ploty)) path_right = np.array([(path_right)], dtype=np.float32) converted_right_path = cv2.perspectiveTransform(path_right, reverse_transform) # Draw bounding box around the lane area overlay_image = np.zeros_like(img) bounding_array = np.concatenate( (converted_left_path[0], np.flipud(converted_right_path[0])) ) bounding_box = np.array([bounding_array], dtype=np.int32) overlay_image = cv2.fillPoly(overlay_image, bounding_box, (0,255, 0)) # this works fine #DEBUG.save_img(overlay_image, "overlay_image_" + name + ".png") result_image = cv2.addWeighted(img, 1, overlay_image, 0.3, 0) #DEBUG.save_img(result_image, "zoutput_" + name + ".png") # use plot to get us an image path_left = list(zip(left_fitx, ploty)) path_left = np.array([(path_left)], dtype=np.float32) converted_left_path = cv2.perspectiveTransform(path_left, reverse_transform) path_right = list(zip(right_fitx, ploty)) path_right = np.array([(path_right)], dtype=np.float32) converted_right_path = cv2.perspectiveTransform(path_right, reverse_transform) # # Curvature & offset in lane # # Calculate values left_curvature = calculate_curvature_meters(left_path) right_curvature = calculate_curvature_meters(right_path) average_curvature = (left_curvature + right_curvature) / 2.0 offset = calculate_offset(left_path[0][0], right_path[0][0], binary_sobelx.shape[1]) # Annotate the image font = cv2.FONT_HERSHEY_SIMPLEX text = 'Radius of curvature = {}m'.format(int(average_curvature)) text2 = 'Offset from center = {}m'.format(offset) result_image = cv2.putText(result_image, text, (100,100), font, 1,(255,255,255),2,cv2.LINE_AA) result_image = cv2.putText(result_image, text2, (100,150), font, 1,(255,255,255),2,cv2.LINE_AA) DEBUG.save_img(result_image, "zzzfinal_output_" + name + ".png") return result_image