def __init__(self, calibration_data_file, smooth_frames = 5, debug = False, failed_frames_dir = 'failed_frames'):
     self.img_processor = ImageProcessor(calibration_data_file)
     self.lane_tracker = LaneDetector(smooth_frames = smooth_frames)
     self.frame_count = 0
     self.fail_count = 0
     self.debug = debug
     self.failed_frames_dir = failed_frames_dir
     self.last_frame = None
     self.processed_frames = None
class VideoProcessor:
    """
    Class used to process a video file and that produces an annotated version with the detected lanes.
    """

    def __init__(self, calibration_data_file, smooth_frames = 5, debug = False, failed_frames_dir = 'failed_frames'):
        self.img_processor = ImageProcessor(calibration_data_file)
        self.lane_tracker = LaneDetector(smooth_frames = smooth_frames)
        self.frame_count = 0
        self.fail_count = 0
        self.debug = debug
        self.failed_frames_dir = failed_frames_dir
        self.last_frame = None
        self.processed_frames = None

    def process_frame(self, img):

        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
       
        undistorted_img, thresholded_img, warped_img = self.img_processor.process_image(img)
        
        _, polyfit, curvature, deviation, fail_code = self.lane_tracker.detect_lanes(warped_img)
        
        fill_color = (0, 255, 0) if fail_code == 0 else (0, 255, 255)

        lane_img = self.lane_tracker.draw_lanes(undistorted_img, polyfit, fill_color = fill_color)
        lane_img = self.img_processor.unwarp_image(lane_img)

        out_image = cv2.addWeighted(undistorted_img, 1.0, lane_img, 1.0, 0)

        font = cv2.FONT_HERSHEY_DUPLEX
        font_color = (0, 255, 0)

        curvature_text = 'Left Curvature: {:.1f}, Right Curvature: {:.1f}'.format(curvature[0], curvature[1])
        offset_text = 'Center Offset: {:.2f} m'.format(deviation)

        cv2.putText(out_image, curvature_text, (30, 60), font, 1, font_color, 2)
        cv2.putText(out_image, offset_text, (30, 90), font, 1, font_color, 2)

        if fail_code > 0:
            self.fail_count += 1
            failed_text = 'Detection Failed: {}'.format(LaneDetector.FAIL_CODES[fail_code])
            cv2.putText(out_image, failed_text, (30, 120), font, 1, (0, 0, 255), 2)
            if self.debug:
                print(failed_text)
                cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '.png'), img)
                cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '_lanes.png'), out_image)
                if self.last_frame is not None: # Saves also the previous frame for comparison
                    cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '_prev.png'), self.last_frame)

        self.frame_count += 1
        self.last_frame = img

        out_image = cv2.cvtColor(out_image, cv2.COLOR_BGR2RGB)

        return out_image

    def process_frame_split(self, img):

        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
       
        undistorted_img, thresholded_img, processed_img = self.img_processor.process_image(img)

        lanes_centroids, polyfit, curvature, deviation, fail_code = self.lane_tracker.detect_lanes(processed_img)
        
        fill_color = (0, 255, 0) if fail_code == 0 else (0, 255, 255)

        lane_img = self.lane_tracker.draw_lanes(undistorted_img, polyfit, fill_color = fill_color)
        lane_img = self.img_processor.unwarp_image(lane_img)

        out_image = cv2.addWeighted(undistorted_img, 1.0, lane_img, 1.0, 0)

        color_img = self.img_processor.color_thresh(undistorted_img) * 255
        gradient_img = self.img_processor.gradient_thresh(undistorted_img) * 255
      
        processed_src = np.array(cv2.merge((thresholded_img, thresholded_img, thresholded_img)), np.uint8)
        src, _ = self.img_processor._warp_coordinates(img)

        src = np.array(src, np.int32)
        
        cv2.polylines(processed_src, [src], True, (0,0,255), 2)

        window_img = np.copy(processed_img)

        window_img = self.lane_tracker.draw_windows(window_img, lanes_centroids, polyfit, blend = True)

        lanes_img = np.copy(out_image)

        font = cv2.FONT_HERSHEY_DUPLEX
        font_color = (0, 255, 0)

        curvature_text = 'Left Curvature: {:.1f}, Right Curvature: {:.1f}'.format(curvature[0], curvature[1])
        offset_text = 'Center Offset: {:.2f} m'.format(deviation)

        cv2.putText(out_image, curvature_text, (30, 60), font, 1, font_color, 2)
        cv2.putText(out_image, offset_text, (30, 90), font, 1, font_color, 2)

        if fail_code > 0:
            self.fail_count += 1
            failed_text = 'Detection Failed: {}'.format(LaneDetector.FAIL_CODES[fail_code])
            cv2.putText(out_image, failed_text, (30, 120), font, 1, (0, 0, 255), 2)
            if self.debug:
                print(failed_text)
                cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '.png'), img)
                cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '_lanes.png'), out_image)
                if self.last_frame is not None: # Saves also the previous frame for comparison
                    cv2.imwrite(os.path.join(self.failed_frames_dir, 'frame' + str(self.frame_count) + '_failed_' + str(fail_code) + '_prev.png'), self.last_frame)

        self.frame_count += 1

        undistorted_img = cv2.cvtColor(undistorted_img, cv2.COLOR_BGR2RGB)
        color_img = cv2.cvtColor(color_img, cv2.COLOR_GRAY2RGB)
        gradient_img = cv2.cvtColor(gradient_img, cv2.COLOR_GRAY2RGB)
        thresholded_img= cv2.cvtColor(thresholded_img, cv2.COLOR_GRAY2RGB)
        processed_src= cv2.cvtColor(processed_src, cv2.COLOR_BGR2RGB)
        processed_img= cv2.cvtColor(processed_img, cv2.COLOR_GRAY2RGB)
        window_img= cv2.cvtColor(window_img, cv2.COLOR_BGR2RGB) 
        lanes_img= cv2.cvtColor(lanes_img, cv2.COLOR_BGR2RGB)
        out_image= cv2.cvtColor(out_image, cv2.COLOR_BGR2RGB)

        return (undistorted_img, color_img, gradient_img, thresholded_img, processed_src, processed_img, window_img, lanes_img, out_image)

    def process_video(self, file_path, output, t_start = None, t_end = None):

        input_clip = VideoFileClip(file_path)
        
        if t_start is not None:
            input_clip = input_clip.subclip(t_start = t_start, t_end = t_end)
        
        output_clip = input_clip.fl_image(self.process_frame)
        output_clip.write_videofile(output, audio = False)

    def process_frame_stage(self, img, idx):
        
        if self.processed_frames is None:
            self.processed_frames = []

        if idx == 0:
            result = self.process_frame_split(img)
            self.processed_frames.append(result)
        else:
            self.frame_count += 1

        return self.processed_frames[self.frame_count - 1][idx]

    def process_video_split(self, file_path, output, t_start = None, t_end = None):

        input_clip = VideoFileClip(file_path)
        
        if t_start is not None:
            input_clip = input_clip.subclip(t_start = t_start, t_end = t_end)

        out_file_prefix = os.path.split(output)[1][:-4]
        
        idx = 0
        output_clip = input_clip.fl_image(lambda img: self.process_frame_stage(img, idx))
        output_clip.write_videofile(out_file_prefix + '_undistoreted.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_color.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_gradient.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_thresholded.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_processed_src.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_processed_dst.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_window.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_lanes.mp4', audio = False)
        idx += 1
        self.frame_count = 0
        output_clip.write_videofile(out_file_prefix + '_final.mp4', audio = False)

        print('Number of failed detection: {}'.format(self.fail_count))
Beispiel #3
0
def upload(filename):
    """ Get the default Notebook ID and process the passed in file"""
    basefile = os.path.basename(filename)
    title, ext = os.path.splitext(basefile)
    body = f"{basefile} uploaded from {platform.node()}\n"
    datatype = mimetypes.guess_type(filename)[0]
    if datatype is None:
        # avoid subscript exception if datatype is None
        if ext in (".url", ".lnk"):
            datatype = "text/plain"
        else:
            datatype = ""
    if datatype == "text/plain":
        body += read_text_note(filename)
        values = set_json_string(title, NOTEBOOK_ID, body)
    if datatype == "text/csv":
        table = read_csv(filename)
        body += tabulate(table,
                         headers="keys",
                         numalign="right",
                         tablefmt="pipe")
        values = set_json_string(title, NOTEBOOK_ID, body)
    elif datatype[:5] == "image":
        img_processor = ImageProcessor(LANGUAGE)
        body += "\n<!---\n"
        try:
            body += img_processor.extract_text_from_image(
                filename, autorotate=AUTOROTATION)
        except TypeError:
            print("Unable to perform OCR on this file.")
        except OSError:
            print(f"Invalid or incomplete file - {filename}")
            return -1
        body += "\n-->\n"
        img = img_processor.encode_image(filename, datatype)
        del img_processor
        values = set_json_string(title, NOTEBOOK_ID, body, img)
    else:
        response = create_resource(filename)
        body += f"[{basefile}](:/{response['id']})"
        values = set_json_string(title, NOTEBOOK_ID, body)
        if response["file_extension"] == "pdf":
            img_processor = ImageProcessor(LANGUAGE)
            if img_processor.pdf_valid(filename):
                # Special handling for PDFs
                body += "\n<!---\n"
                body += img_processor.extract_text_from_pdf(filename)
                body += "\n-->\n"
                previewfile = img_processor.PREVIEWFILE
                if not os.path.exists(previewfile):
                    previewfile = img_processor.pdf_page_to_image(filename)
                img = img_processor.encode_image(previewfile, "image/png")
                os.remove(previewfile)
                values = set_json_string(title, NOTEBOOK_ID, body, img)

    response = requests.post(ENDPOINT + "/notes" + TOKEN, data=values)
    # print(response)
    # print(response.text)
    if response.status_code == 200:
        if AUTOTAG:
            apply_tags(body, response.json().get("id"))
        print(f"Placed note into notebook {NOTEBOOK_ID}: {NOTEBOOK_NAME}")
        if os.path.isdir(MOVETO):
            moveto_filename = os.path.join(MOVETO, basefile)
            print(moveto_filename)
            if os.path.exists(moveto_filename):
                print(f"{basefile} exists in moveto dir, not moving!")
            else:
                try:
                    # Give it a few seconds to release file lock
                    time.sleep(3)
                    shutil.move(filename, MOVETO)
                except IOError:
                    print(f"File Locked-unable to move {filename}")
        return 0
    else:
        print("ERROR! NOTE NOT CREATED")
        print("Something went wrong corrupt file or note > 10MB?")
        return -1
Beispiel #4
0
                        default=80,
                        help='Sliding window height')

    parser.add_argument('--w_margin',
                        type=int,
                        default=35,
                        help='Sliding window margin from center')

    args = parser.parse_args()

    img_files = []

    for ext in ('*.png', '*.jpg'):
        img_files.extend(glob(os.path.join(args.dir, ext)))

    img_processor = ImageProcessor(args.calibration_data_file)
    lane_tracker = LaneDetector(window_width=args.w_width,
                                window_height=args.w_height,
                                margin=args.w_margin,
                                smooth_frames=0)

    for img_file in tqdm(img_files, unit=' images', desc='Image processing'):

        print(img_file)
        input_img = cv2.imread(img_file)

        undistorted_img, thresholded_img, processed_img = img_processor.process_image(
            input_img)

        out_file_prefix = os.path.join(args.output,
                                       os.path.split(img_file)[1][:-4])
Beispiel #5
0
 def init_vid_process(self, source, pipe, array, mode, cap):
     mode = self.check_mode_availability(source, mode)
     self.cam_process = ImageProcessor(source, mode, pipe, array, cap)
     self.vid_process = Process(target=self.cam_process.run_vid, args=())
     self.vid_process.start()
Beispiel #6
0
 def init_process(self, source, pipe, array, mode, cap):
     mode = self.check_mode_availability(source, mode)
     self.cam_process = ImageProcessor(source, mode, pipe, array, cap)
     self.cam_process.start() 
Beispiel #7
0
class EyeCamera(camera.Camera):

    def __init__(self, name=None, mode=(192,192,120)):
        super().__init__(name)
        self.mode = mode
        self.cam_process = None
        self.vid_process = None
        self.shared_array = self.create_shared_array(mode)
        self.detector = Detector3D()
        self.bbox = None
        self.pos = None
        
        self.detector.update_properties({'2d':{'pupil_size_max':180}})
        self.detector.update_properties({'2d':{'pupil_size_min':10}})
        self.countdown = 5

    def init_process(self, source, pipe, array, mode, cap):
        mode = self.check_mode_availability(source, mode)
        self.cam_process = ImageProcessor(source, mode, pipe, array, cap)
        self.cam_process.start() 

    def init_vid_process(self, source, pipe, array, mode, cap):
        mode = self.check_mode_availability(source, mode)
        self.cam_process = ImageProcessor(source, mode, pipe, array, cap)
        self.vid_process = Process(target=self.cam_process.run_vid, args=())
        self.vid_process.start()

    def join_process(self):
        self.cam_process.join(10)

    def join_vid_process(self):
        self.vid_process.join(3)

    def create_shared_array(self, mode):
        w = mode[0]
        h = mode[1]
        return Array(ctypes.c_uint8, h*w*3, lock=False)

    def check_mode_availability(self, source, mode):
        dev_list = uvc.device_list()
        cap = uvc.Capture(dev_list[source]['uid'])
        if mode not in cap.avaible_modes:
            m = cap.avaible_modes[0]
            mode = (m[1], m[0], m[2])
            self.shared_array = self.create_shared_array(mode)
            self.mode = mode
        return mode

    def process(self, img):
        if img is None:
            return
        height, width = img.shape[0], img.shape[1]
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        timestamp = uvc.get_time_monotonic()
        roi = None
        if self.bbox is not None:
            xmin, ymin, w, h = self.bbox
            roi = Roi(xmin, ymin, xmin+w, ymin+h)
        result = self.detector.detect(gray, timestamp, roi=roi)
        #print(result)
        if result["model_confidence"] > 0.25:
            sphere = result["projected_sphere"]
            self.__draw_ellipse(sphere, img, (255,120,120), 1) 
        if result["confidence"] > 0.5:
            n = np.array(result['circle_3d']['normal']) 
            self.bbox = self.__get_bbox(result, img)    
            self.__draw_tracking_info(result, img)
            # cv2.imshow("testando", img)
            # cv2.waitKey(1)
            self.pos = np.array([n[0], n[1], n[2], time.monotonic()])
            self.countdown = 5
        else:
            self.countdown -= 1
            if self.countdown <= 0:
                self.pos = None
                self.bbox = None
        return img

    def freeze_model(self):
         self.detector.update_properties({
             "3d": {"model_is_frozen": True}
             })

    def unfreeze_model(self):
        self.detector.update_properties({
             "3d": {"model_is_frozen": False}
             })

    def __get_bbox(self, result, img):
        r = result['diameter']
        point = result['ellipse']['center']
        x1 = point[0]-r*0.8
        y1 = point[1]-r*0.8
        x2 = point[0]+r*0.8
        y2 = point[1]+r*0.8
        x1 = self.__test_boundaries(x1, img.shape[1])
        y1 = self.__test_boundaries(y1, img.shape[0])
        x2 = self.__test_boundaries(x2, img.shape[1])
        y2 = self.__test_boundaries(y2, img.shape[0])
        w = x2-x1
        h = y2-y1
        cv2.rectangle(img, self.bbox, (125,80,80), 2, 1)
        return int(x1),int(y1),int(w),int(h)


    def __test_boundaries(self, x, lim):
        if x < 0:
            return 0
        if x >= lim:
            return lim-1
        return x


    
    def __draw_tracking_info(self, result, img, color=(255,120,120)):
        ellipse = result["ellipse"]
        normal = result["circle_3d"]["normal"]
        center = tuple(int(v) for v in ellipse["center"])
        cv2.drawMarker(img, center, (0,255,0), cv2.MARKER_CROSS, 12, 1)
        self.__draw_ellipse(ellipse, img, (0,0,255))
        dest_pos = (int(center[0]+normal[0]*60), int(center[1]+normal[1]*60))
        cv2.line(img, center, dest_pos, (85,175,20),2)
        # if self.bbox is not None:
        #     cv2.rectangle(img, self.bbox, (120,255,120), 2, 1)
        


    def __draw_ellipse(self, ellipse, img, color, thickness=2):
        center = tuple(int(v) for v in ellipse["center"])
        axes = tuple(int(v/2) for v in ellipse["axes"])
        rad = ellipse["angle"]
        cv2.ellipse(img, center, axes, rad, 0, 360, color, 2)


    def reset_model(self):
        self.detector.reset_model()


    def get_processed_data(self):
        return self.pos