def main():
    if (len(sys.argv) > 1) and isinstance(sys.argv[1], str):
        filename = sys.argv[1]
    else:
        filename = 'challenge_video.mp4'

    print('Processing file ' + filename)

    white_output = 'processed_videos/' + filename
    clip1 = VideoFileClip('source_videos/' + filename)  #.subclip(0,5)

    # calculate matrices for perspective transformation
    target_left_x = 300
    target_right_x = 1002
    target_top_y = 0
    target_bottom_y = 690
    src_points = np.float32([[283, 664], [548, 480], [736, 480], [1019, 664]])
    dst_points = np.float32([[target_left_x, target_bottom_y],
                             [target_left_x, target_top_y],
                             [target_right_x, target_top_y],
                             [target_right_x, target_bottom_y]])

    # transformation to bird's eye view
    M = cv2.getPerspectiveTransform(src_points, dst_points)
    # transformation back to normal view
    Mi = cv2.getPerspectiveTransform(dst_points, src_points)

    # calculate or load camera calibration
    calCam = CalibrateCamera.load()

    if calCam == None:
        images = glob.glob('camera_cal/calibration*.jpg')

        calCam = CalibrateCamera()

        calCam.findCorners(images, (9, 6))

        calCam.calibrateCamera()

        calCam.write()

    # class which will process the images, initialize with image size and
    # transformation matrices
    ld = ProcessImage()
    ld.fit((720, 1280), M, Mi, calCam=calCam)

    white_clip = clip1.fl_image(ld.process_image)  # color images

    white_clip.write_videofile(white_output, audio=False)
Пример #2
0
    def fit(self, shape, M, MInverse, roi=None, calCam=None):
        """
        First call before processing images
        """
        self.shape = shape

        # region of interest
        if roi != None:
            self.roi = roi
        else:
            self.roi = {
                'bottom_y': shape[0],
                'bottom_x_left': int(shape[1] * 0.05),
                'bottom_x_right': int(shape[1] * 0.95),
                'top_y': int(shape[0] * 0.6),
                'top_x_left': int(shape[1] * 0.45),
                'top_x_right': int(shape[1] * 0.55),
            }
            self.roi.update({
                'top_center':
                int((self.roi['top_x_left'] + self.roi['top_x_right']) / 2)
            })

        if calCam is not None:
            self.calCam = calCam
        else:
            self.calCam = CalibrateCamera.load()

            if self.calCam is None:
                images = glob.glob('camera_cal/calibration*.jpg')
                self.calCam = CalibrateCamera()
                self.calCam.findCorners(images, (9, 6))
                self.calCam.calibrateCamera()
                self.calCam.write()

        self.laneFit = LaneFit()

        self.M = M
        self.MInverse = MInverse
        self.frame = 0
        self.update = False
Пример #3
0
def main(args):
    #camera calibration
    calCam = CalibrateCamera.load()

    # if no precalculated data is available start calculation
    if calCam == None:
        images = glob.glob('data/camera_cal/*.jpg')
        calCam = CalibrateCamera()
        calCam.findCorners(images, (9, 6))
        calCam.calibrateCamera()
        calCam.write()

    # create subscriber class
    ims = image_subscriber(calCam)

    rospy.init_node('show_robot_camera')

    rate = rospy.Rate(30)

    while not rospy.is_shutdown():
        ims.show_image()
        rate.sleep()

    cv2.destroyAllWindows()
Пример #4
0
class ProcessImageLane():
    def __init__(self):
        self.shape = None
        self.roi = None
        self.calCam = None
        self.laneFit = None
        self.image_cnt = 0
        self.DEBUG_IMAGE = True
        self.DEBUG_IMAGE_FOLDER = 'challenge_debug'
        self.DEBUG_VIDEO = False
        self.segmentation = 1

    def fit(self, shape, M, MInverse, roi=None, calCam=None):
        """
        First call before processing images
        """
        self.shape = shape

        # region of interest
        if roi != None:
            self.roi = roi
        else:
            self.roi = {
                'bottom_y': shape[0],
                'bottom_x_left': int(shape[1] * 0.05),
                'bottom_x_right': int(shape[1] * 0.95),
                'top_y': int(shape[0] * 0.6),
                'top_x_left': int(shape[1] * 0.45),
                'top_x_right': int(shape[1] * 0.55),
            }
            self.roi.update({
                'top_center':
                int((self.roi['top_x_left'] + self.roi['top_x_right']) / 2)
            })

        if calCam is not None:
            self.calCam = calCam
        else:
            self.calCam = CalibrateCamera.load()

            if self.calCam is None:
                images = glob.glob('camera_cal/calibration*.jpg')
                self.calCam = CalibrateCamera()
                self.calCam.findCorners(images, (9, 6))
                self.calCam.calibrateCamera()
                self.calCam.write()

        self.laneFit = LaneFit()

        self.M = M
        self.MInverse = MInverse
        self.frame = 0
        self.update = False

    def writeInfo(self, img, laneparams):
        """
        Writes information to the image
        """
        # empty image
        box_img = np.zeros_like(img).astype(np.uint8)

        # draw rectangle and arrow for position deviation
        box_img = cv2.rectangle(box_img, (10, 10), (int(1280 / 2 - 10), 150),
                                (0, 0, 100),
                                thickness=cv2.FILLED)
        box_img = cv2.rectangle(box_img, (int(1280 / 2 - 10), 10),
                                (1280 - 10, 150), (0, 0, 100),
                                thickness=cv2.FILLED)
        box_img = cv2.arrowedLine(
            box_img, (500, 60),
            (int(500 + laneparams['middle_phys'] * 200), 60), (255, 0, 0), 5)

        img = cv2.addWeighted(img, 1.0, box_img, 1.0, 0.)

        font = cv2.FONT_HERSHEY_SIMPLEX
        pos_str = 'Left curve:  {:06.0f}'.format(laneparams['left_curverad'])
        pos_str2 = 'Right curve: {:06.0f}'.format(laneparams['right_curverad'])
        pos_str3 = 'Middle: {:.2f}m'.format(laneparams['middle_phys'])
        frame_str = 'Frame: {}'.format(self.frame)

        left_pos = 40
        top_pos = 40
        delta_height = 30
        # write text to image
        cv2.putText(img, pos_str, (left_pos, top_pos), font, 0.8,
                    (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img, pos_str2, (left_pos, top_pos + delta_height), font,
                    0.8, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img, pos_str3, (400, top_pos), font, 0.8, (255, 255, 255),
                    1, cv2.LINE_AA)
        cv2.putText(img, frame_str, (left_pos, top_pos + 3 * delta_height),
                    font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)

        return img

    def process_image(self, img_orig):
        """
        Processes an image
        """
        t0 = time()
        img = self.calCam.undistort(img_orig)

        if self.DEBUG_IMAGE:
            img_savename = 'image{0:04d}.jpg'.format(self.image_cnt)
            cv2.imwrite(self.DEBUG_IMAGE_FOLDER + '/original/' + img_savename,
                        cv2.cvtColor(img_orig, cv2.COLOR_BGR2RGB))
            cv2.imwrite(self.DEBUG_IMAGE_FOLDER + '/undist/' + img_savename,
                        cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

        img_undist = img
        ksize = 9

        # gray conversion
        gray = img2gray(img)

        # Apply each of the thresholding functions
        if self.segmentation == 0:
            # magnitude and direction of edges, color
            mag_binary = mag_thresh(gray,
                                    sobel_kernel=ksize,
                                    mag_thresh=(20, 255))
            dir_binary = dir_threshold(gray,
                                       sobel_kernel=ksize,
                                       thresh=(np.pi / 4 * 0.9,
                                               np.pi / 4 * 1.5))
            color_seg = color_segmentation(img)

            seg_img_raw = color_seg & mag_binary & dir_binary

        else:
            # color segmentation and canny edge detection
            color_seg = color_segmentation(img)

            kernel_size = 5
            blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
            canny = cv2.Canny(blur_gray, 40, 80).astype(np.uint8) * 255
            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
            # dilate canny edges which are very sharp
            canny = cv2.dilate(canny, kernel, iterations=2)

            # segmented image with color and canny
            seg_img_raw = (color_seg & canny)

            if self.DEBUG_IMAGE:
                cv2.imwrite(
                    self.DEBUG_IMAGE_FOLDER + '/seg_color/' + img_savename,
                    color_seg.astype(np.uint8) * 255)
                cv2.imwrite(
                    self.DEBUG_IMAGE_FOLDER + '/seg_canny/' + img_savename,
                    canny.astype(np.uint8) * 255)
                cv2.imwrite(
                    self.DEBUG_IMAGE_FOLDER + '/seg_comb/' + img_savename,
                    seg_img_raw.astype(np.uint8) * 255)

        seg_img = seg_img_raw.astype(np.uint8) * 255

        seg_img[690:, :] = 0

        # mask image
        # region of interest not used
        #seg_img, vertices = mask_region_of_interest(seg_img, self.roi)
        seg_img = np.dstack((seg_img, seg_img, seg_img))

        #visualization = np.dstack((np.zeros(dir_binary.shape), (dir_binary & mag_binary), color_seg)).astype(np.uint8) * 255

        # warp to birds eye perspective
        seg_img_warped = cv2.warpPerspective(
            seg_img,
            self.M, (seg_img.shape[1], seg_img.shape[0]),
            flags=cv2.INTER_LINEAR)

        # thresholding for interpolated pixels
        seg_img_warped = (seg_img_warped > 100).astype(np.uint8) * 255

        if self.DEBUG_IMAGE:
            cv2.imwrite(
                self.DEBUG_IMAGE_FOLDER + '/seg_warped/' + img_savename,
                seg_img_warped)
            #undist_img_warped = cv2.warpPerspective(img_undist, self.M, (img_undist.shape[1], img_undist.shape[0]), flags=cv2.INTER_LINEAR)
            #cv2.imwrite(self.DEBUG_IMAGE_FOLDER + '/undist_warped/'+img_savename, undist_img_warped)

        # do LaneFit algorithm on image
        laneparams = self.laneFit.procVideoImg(seg_img_warped,
                                               margin=60,
                                               numwin=20)

        lane_img = laneparams['img']

        if self.DEBUG_IMAGE:
            comb = cv2.addWeighted(seg_img_warped, 0.5, lane_img, 0.8, 0)
            cv2.imwrite(self.DEBUG_IMAGE_FOLDER + '/combined/' + img_savename,
                        cv2.cvtColor(comb, cv2.COLOR_BGR2RGB))

        lane_img_unwarped = cv2.warpPerspective(
            lane_img,
            self.MInverse, (lane_img.shape[1], lane_img.shape[0]),
            flags=cv2.INTER_LINEAR)

        # combine original image with detection
        img = cv2.addWeighted(img, 1, lane_img_unwarped, 0.7, 0)

        # time measurement
        t1 = time()
        logging.info('process_image: runtime = ' + str(t1 - t0))

        # debug video with different segmentations used in this algorithm
        if self.DEBUG_VIDEO:
            img = np.dstack(
                (np.zeros_like(seg_img_raw), canny, color_seg)).astype(
                    np.uint8) * 255
            img = cv2.addWeighted(img, 1, lane_img_unwarped, 0.9, 0)

        if self.DEBUG_IMAGE:
            cv2.imwrite(self.DEBUG_IMAGE_FOLDER + '/result/' + img_savename,
                        cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            self.image_cnt += 1  # for number of debug image

        undist_img_warped = cv2.warpPerspective(
            img_undist,
            self.M, (img_undist.shape[1], img_undist.shape[0]),
            flags=cv2.INTER_LINEAR)

        # add smaller images of the segmented and warped image
        y_offset = 0
        output_size = (720, 1280, 3)
        ret_img = np.zeros(output_size).astype(np.uint8)

        warped_smaller = cv2.resize(undist_img_warped, (0, 0),
                                    fx=0.15,
                                    fy=0.15)
        warped_semented_smaller = cv2.resize(comb, (0, 0), fx=0.15, fy=0.15)
        warped_combined_smaller = cv2.addWeighted(warped_smaller, 1,
                                                  warped_semented_smaller, 0.7,
                                                  0)

        color_smaller = cv2.resize(
            color_seg.astype(np.uint8), (0, 0), fx=0.15, fy=0.15).reshape(
                (108, 192, 1)) * 255
        canny_smaller = cv2.resize(
            canny.astype(np.uint8), (0, 0), fx=0.15, fy=0.15).reshape(
                (108, 192, 1)) * 255
        combined_smaller = cv2.resize(
            (color_seg & canny).astype(np.uint8),
            (0, 0), fx=0.15, fy=0.15).reshape((108, 192, 1)) * 255
        stacked_smaller = np.dstack(
            (combined_smaller, canny_smaller, color_smaller)).astype(np.uint8)

        ret_img[y_offset:img.shape[0] + y_offset, :img.shape[1], :] = img

        # write information to image
        ret_img = self.writeInfo(ret_img, laneparams)

        offset_small = 26
        offset_x_small = 684
        ret_img[offset_small:offset_small + 108,
                offset_x_small:offset_x_small + 192, :] = stacked_smaller
        ret_img[offset_small:offset_small + 108, offset_x_small +
                200:offset_x_small + 392, :] = warped_combined_smaller

        self.frame += 1

        return ret_img
Пример #5
0
def main():
    calCam = CalibrateCamera.load()

    if calCam == None:
        images = glob.glob('camera_cal/calibration*.jpg')

        calCam = CalibrateCamera()

        calCam.findCorners(images, (9, 6))

        calCam.calibrateCamera()

        calCam.write()

    print(calCam.mtx)
    print(calCam.dist)
    # Read in an image
    img_orig = mpimg.imread('test_images/straight_lines2.jpg')
    #img_orig = mpimg.imread('test_images/test6.jpg')
    #img_orig = (mpimg.imread('test_images/shadow_05.png') * 255).astype(np.uint8)
    #img_orig = (mpimg.imread('test_images/challenge_02.png') * 255).astype(np.uint8)
    #img_orig = mpimg.imread('camera_cal/calibration1.jpg')

    img = calCam.undistort(img_orig)

    # define region of interest
    roi = {
        'bottom_y': img.shape[0],
        'bottom_x_left': int(img.shape[1] * 0.05),
        'bottom_x_right': int(img.shape[1] * 0.95),
        'top_y': int(img.shape[0] * 0.6),
        'top_x_left': int(img.shape[1] * 0.45),
        'top_x_right': int(img.shape[1] * 0.55),
    }
    roi.update(
        {'top_center': int((roi['top_x_left'] + roi['top_x_right']) / 2)})

    horizon = 425

    if False:
        original_bottom_left_x = 283
        target_left_x = 300
        target_right_x = 1002
        target_top_y = 0
        target_bottom_y = 685
        src_points = np.float32([[283, 664], [552, 480], [736, 480],
                                 [1015, 664]])
        dst_points = np.float32([[target_left_x, target_bottom_y],
                                 [target_left_x, target_top_y],
                                 [target_right_x, target_top_y],
                                 [target_right_x, target_bottom_y]])
    else:
        target_left_x = 300
        target_right_x = 1002
        target_top_y = 0
        target_bottom_y = 690
        src_points = np.float32([[283, 664], [548, 480], [736, 480],
                                 [1019, 664]])
        dst_points = np.float32([[target_left_x, target_bottom_y],
                                 [target_left_x, target_top_y],
                                 [target_right_x, target_top_y],
                                 [target_right_x, target_bottom_y]])

    M = cv2.getPerspectiveTransform(src_points, dst_points)
    Mi = cv2.getPerspectiveTransform(dst_points, src_points)

    ksize = 15  # Choose a larger odd number to smooth gradient measurements

    #hls = cv2.cvtColor(img[roi['top_y']:,:,:], cv2.COLOR_RGB2HLS)
    hls = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(32, 32))
    hls[:, :, 1] = clahe.apply(hls[:, :, 1])
    #hls[:,:,1] = cv2.equalizeHist(hls[:,:,1])
    claheimg = cv2.cvtColor(hls, cv2.COLOR_HLS2RGB)

    gray = img2gray(img)

    # Apply each of the thresholding functions
    gradx = abs_sobel_thresh(gray,
                             orient='x',
                             sobel_kernel=ksize,
                             thresh=(20, 255))
    grady = abs_sobel_thresh(gray,
                             orient='y',
                             sobel_kernel=ksize,
                             thresh=(30, 255))
    mag_binary = mag_thresh(gray, sobel_kernel=ksize, mag_thresh=(30, 255))
    color_mag = mag_thresh(gray, sobel_kernel=ksize, mag_thresh=(5, 255))
    dir_binary = dir_threshold(
        gray, sobel_kernel=ksize,
        thresh=(1.0, 1.3))  #thresh=(np.pi/4*1.0, np.pi/4*1.2))

    kernel_size = 5
    blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
    #canny = cv2.Canny(blur_gray, 120, 200)
    canny = cv2.Canny(blur_gray, 40, 80)
    canny[670:, :] = 0

    canny = np.dstack((canny, canny, canny))
    #print(src_points.reshape((-1,1,2)).astype(np.int32))
    #pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
    #src_points = pts.reshape((-1,1,2))
    #print(src_points)
    canny = cv2.polylines(canny,
                          [src_points.reshape((-1, 1, 2)).astype(np.int32)],
                          True, (0, 255, 255),
                          thickness=1)

    canny_warped = cv2.warpPerspective(canny,
                                       M, (canny.shape[1], canny.shape[0]),
                                       flags=cv2.INTER_LINEAR)
    #canny_warped = (canny_warped > 120).astype(np.uint8) * 255

    #kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    #canny_warped = cv2.dilate(canny_warped, kernel, iterations=1)
    #canny_warped = cv2.erode(canny_warped, kernel, iterations=1)

    plt.imshow(canny)
    plt.show()

    return

    color_seg = color_segmentation(img,
                                   l_thresh=[30, 255],
                                   s_thresh=[160, 255])

    seg_img_raw = (
        (color_seg & color_mag & dir_binary) | (dir_binary & mag_binary)
    )  #(color_seg | (dir_binary & mag_binary)).astype(np.uint8) * 255

    # mask image
    seg_img, vertices = mask_region_of_interest(
        seg_img_raw.astype(np.uint8) * 255, roi)
    seg_img_roi = seg_img
    #visualization = np.dstack((seg_img_raw, (dir_binary & mag_binary), color_seg)).astype(np.uint8) * 255
    visualization = np.dstack(
        (seg_img_raw, color_seg,
         (dir_binary & mag_binary))).astype(np.uint8) * 255

    seg_img = np.dstack((seg_img, seg_img, seg_img))
    seg_img_warped = cv2.warpPerspective(seg_img,
                                         M,
                                         (seg_img.shape[1], seg_img.shape[0]),
                                         flags=cv2.INTER_LINEAR)

    histogram = np.sum(seg_img_warped[gradx.shape[0] // 2:, :-2, 0], axis=0)

    midpoint = np.int(histogram.shape[0] / 2)

    print('Midpoint = ' + str(midpoint))
    leftx_base = np.argmax(histogram[:midpoint])
    rightx_base = np.argmax(histogram[midpoint:]) + midpoint
    print('Bases = ' + str((leftx_base, rightx_base)))

    laneFit = LaneFit()
    left_fit, right_fit, lane_img, _, _, _ = laneFit.fitLanes(seg_img_warped,
                                                              leftx_base,
                                                              rightx_base,
                                                              margin=60)

    lane_img_unwarped = cv2.warpPerspective(
        lane_img,
        Mi, (lane_img.shape[1], lane_img.shape[0]),
        flags=cv2.INTER_LINEAR)

    # Plot the result
    gs = grd.GridSpec(3,
                      2,
                      height_ratios=[10, 10, 10],
                      width_ratios=[1, 1],
                      wspace=0.1)

    ax = plt.subplot(gs[0, 0])
    ax.imshow(img_orig)
    ax.set_title('Original Image', fontsize=10)

    ax = plt.subplot(gs[0, 1])
    ax.imshow(img)
    ax.set_title('Undistorted Image', fontsize=10)

    if False:
        ax = plt.subplot(gs[1, 0])
        ploty = np.linspace(0, lane_img.shape[0] - 1, lane_img.shape[0])
        left_fitx = left_fit[0] * ploty**2 + left_fit[1] * ploty + left_fit[2]
        right_fitx = right_fit[0] * ploty**2 + right_fit[
            1] * ploty + right_fit[2]

        ax.imshow(lane_img)
        ax.plot(left_fitx, ploty, color='yellow')
        ax.plot(right_fitx, ploty, color='yellow')

        ax.set_title('Lane fit', fontsize=10)
    else:
        ax = plt.subplot(gs[1, 0])
        #ax.imshow(claheimg)
        ax.imshow(canny, cmap='gray')

    ax = plt.subplot(gs[1, 1])
    ax.imshow(blur_gray, cmap='gray')
    ax.set_title('Combined', fontsize=10)

    ax = plt.subplot(gs[2, 0])
    ax.imshow(visualization)
    ax.set_title('Visualization', fontsize=10)

    ax = plt.subplot(gs[2, 1])
    #ax.plot(histogram)
    ax.imshow(lane_img_unwarped)
    ax.set_title('Histogram', fontsize=10)

    plt.show()