Esempio n. 1
0
class AdvancedLaneLine:
    def __init__(self, session=random_prefix(), debug=False):
        # calibrate camera
        images = glob.glob("./camera_cal/calibration*.jpg")
        self.ret, self.mtx, self.dist, self.rvecs, self.tvecs = calibrate_camera(images)

        # previous lines
        self.left_line = Line()
        self.right_line = Line()

        # perspective transform coordinates
        self.src, self.dst = get_src_dst_coordinates()
        
        # debug purposes
        self.frame_number = 0
        self.session = session
        self.debug = debug
        
        # counters
        self.sliding_window_count = 0
        self.from_existing_count = 0
        return

    # get the session/frame/file name for the given file name suffix
    def get_session_frame_file_name(self, file_suffix):
        return "{}_{}_{}".format(self.session, self.frame_number, file_suffix)

    # save intermediate images, debug purposes 
    def save_image(self, img, suffix="out", out_folder="output"):
        if self.debug == True:
            outfile = "./{}/{}.jpg".format(out_folder, self.get_session_frame_file_name(suffix))
            mpimg.imsave(outfile, img)
        return

    def find_lane_lines(self, unwarp):
        if self.left_line.detected == False or self.right_line.detected == False:
            sliding_windows_list, leftx, lefty, rightx, righty = sliding_windows2(unwarp)
            slide_win_img = sliding_windows_image(unwarp, sliding_windows_list)
            self.save_image(slide_win_img, "slide")
            self.sliding_window_count += 1
        else:
            leftx, lefty, rightx, righty = find_lane_lines_from_existing(unwarp, self.left_line.best_fit, self.right_line.best_fit)
            self.from_existing_count += 1

        left_fit, right_fit = (None, None)
        # remove outliers
        if len(leftx) > 0:
            leftx, lefty = outlier_removal(leftx, lefty)
            if len(leftx) > 2:
                left_fit = np.polyfit(lefty, leftx, 2)
        if len(rightx) > 0:
            rightx, righty = outlier_removal(rightx, righty)
            if len(rightx) > 2:
                right_fit = np.polyfit(righty, rightx, 2)
        if left_fit is not None or right_fit is not None:
            ploty = np.linspace(0, unwarp.shape[0]-1, unwarp.shape[0])
            left_fitx, right_fitx = (None, None)
            if left_fit is not None:
                left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
            if right_fit is not None:
                right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]

        if left_fitx is not None and right_fitx is not None:
            # Create an output image to draw on and  visualize the result
            lines_out = np.dstack((unwarp, unwarp, unwarp))*255
            ploty = np.linspace(0, unwarp.shape[0]-1, unwarp.shape[0])

            # Recast the x and y points into usable format for cv2.fillPoly()
            pts_left = np.array([np.transpose(np.vstack([left_fitx, ploty]))])
            pts_right = np.array([np.flipud(np.transpose(np.vstack([right_fitx, ploty])))])
            pts = np.hstack((pts_left, pts_right))
            # Draw the lane onto the warped blank image
            cv2.polylines(lines_out, np.int32([pts]), 1, (255,255,0))
            self.save_image(lines_out, "lines")
            
            # check if the fits are looking valid, if not for the first frame
            if self.left_line.best_fit is None or self.right_line.best_fit is None or (is_parallel(left_fit, right_fit) and is_distance_in_range(left_fitx, right_fitx)):
                self.left_line.add(left_fit)
                self.right_line.add(right_fit)
                return

        # reset the flags so that next time, it will do sliding windows
        self.left_line.detected = False
        self.right_line.detected = False
        return
    
    def overlay_lane_lines(self, undist, unwarp, Minv):
        out = overlay_image(undist, unwarp, Minv, self.left_line.best_fit, self.right_line.best_fit)
        return out
    
    def image_pipeline(self, image):
        self.save_image(image, "org")
        # 1. undistort image
        undist = undistort_image(image, self.mtx, self.dist)
        self.save_image(undist, "undist")
        # 2. color and gradient threshold
        threshold = color_gradient_threshold(undist)
        self.save_image(threshold,"thres")
        # 3. perspective transform
        unwarp, M, Minv = unwarp_image(threshold, self.src, self.dst)
        self.save_image(unwarp, "unwarp")
        # 4. find lane lines
        self.find_lane_lines(unwarp)
        # 5. overlay lane lines on image
        out_img = self.overlay_lane_lines(undist, unwarp, Minv)
        self.save_image(out_img, "out")
        # increment the frame counter
        self.frame_number += 1
        return out_img