class ExtractorPlayer(object): def __init__(self, file_path, calibration): self.calibration = calibration self.clip = VideoFileClip(file_path) self.n_frames = np.round(self.clip.fps * self.clip.duration).astype(np.int) self.clip_time = 0 self.extractor = Extractor(thresh=self._load_thresholds(), th_change_callback=self.th_change_callback) self._create_display_windows() def _create_display_windows(self): window_grid = WindowGrid() pos_x, pos_y, width, height = window_grid.next() self.win_input_image = 'Input image' cv2.namedWindow(self.win_input_image, cv2.WINDOW_NORMAL) cv2.moveWindow(self.win_input_image, pos_x, pos_y) cv2.resizeWindow(self.win_input_image, width, height) cv2.createTrackbar('frame', self.win_input_image, 0, self.n_frames - 1, self.frame_slider_callback) self.extractor.init_show(window_grid) def _process_frame(self): rgb_image = self.clip.get_frame(self.clip_time) rgb_image = self.calibration.undistort(rgb_image) images = { 'rgb': rgb_image, 'gray': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY), 'hls': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2HLS), 'bgr': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR), } self.extractor.apply(images) cv2.imshow(self.win_input_image, images['bgr']) self.extractor.show() def process(self): pause = False while 1: if not pause and (self.clip_time < self.clip.duration): self._process_frame() frame_idx = np.round(self.clip.fps * self.clip_time).astype(np.int) cv2.setTrackbarPos('frame', self.win_input_image, frame_idx) self.clip_time += 1.0 / self.clip.fps k = cv2.waitKey(20) & 0xff if k == ascii_dict['space']: pause = not pause # toggle elif k == ascii_dict['esc']: break self._save_thresholds() cv2.destroyAllWindows() def frame_slider_callback(self, value): self.clip_time = value / self.clip.fps self._process_frame() def th_change_callback(self): self._process_frame() def _load_thresholds(self): if not os.path.isfile(thresholds_path): return dict() with open(thresholds_path, 'rb') as fid: thresholds = pickle.load(fid) print("Loaded thresholds:") print(thresholds) return thresholds def _save_thresholds(self): thresholds = self.extractor.get_thresholds() print("Saving thresholds:") print(thresholds) with open(thresholds_path, 'wb') as fid: pickle.dump(thresholds, fid)
class LaneFindingPipeline(object): def __init__(self): if camera_calibration_available(): print("Loading camera calibration") self.calibration = load_camera_calibration() else: print("Running camera calibration") self.calibration = Calibrate() store_camera_calibration(self.calibration) self.extractor = Extractor(thresh=load_thresholds()) self.perspective = load_perspective() self.detector = Detector(self.perspective) def player(self, video_path='../input/project_video.mp4'): for rgb_image in VideoFileClip(video_path).iter_frames(): bgr_image = self.process_frame(rgb_image) cv2.imshow("Lane Detection", bgr_image) k = cv2.waitKey(20) & 0xff if k == 27: break # Quit by pressing Esc if k == 32: cv2.waitKey() # Pause by pressing space else: cv2.waitKey() cv2.destroyAllWindows() def create_video(self, video_path='../input/project_video.mp4', output_video_path='../output/project_video.mp4'): clip = VideoFileClip(video_path).fl_image(self.process_frame_rgb) clip.write_videofile(output_video_path, audio=False) def process_frame(self, rgb_image): rgb_image = self.calibration.undistort(rgb_image) # Calculate images images = { 'rgb': rgb_image, 'gray': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY), 'hls': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2HLS), 'bgr': cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR), } # Extract possible lane lines pixels into a binary image. extracted_image = self.extractor.apply(images).astype(np.uint8) # Warp perspective to birds-eye-view h, w = extracted_image.shape perspective_image = cv2.warpPerspective( extracted_image, self.perspective['transformation_matrix'], (w, h), flags=cv2.INTER_LINEAR) # Fit lines to extracted lane line pixels and calculate curvature and vehicle lane position. lines_curvature, lane_center_offset = self.detector.find( perspective_image) # Draw information directly into the visualized image. images['bgr'] = self.draw_overlays(images['bgr'], lines_curvature, lane_center_offset, extracted_image) return images['bgr'] def process_frame_rgb(self, rgb_image): """Process frame and convert output to RGB format""" bgr_image = self.process_frame(rgb_image) return cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) def draw_overlays(self, bgr_image, lines_curvature, lane_center_offset, extracted_image): bgr_image = overlay_lane_detection( bgr_image, self.detector, self.perspective['inv_transformation_matrix']) bgr_image = overlay_lane_curvature(bgr_image, lines_curvature) bgr_image = overlay_lane_center_offset(bgr_image, lane_center_offset) bgr_image = overlay_extracted_image(bgr_image, extracted_image) bgr_image = overlay_detection_image(bgr_image, Line.demo_image) bgr_image = overlay_perspective_image( bgr_image, self.perspective['transformation_matrix']) return bgr_image