<jupyter_start><jupyter_text>Advanced Lane Finding ProjectThe goals / steps of this project are the following:* Compute the camera calibration matrix and distortion coefficients given a set of chessboard images.* Apply a distortion correction to raw images.* Use color transforms, gradients, etc., to create a thresholded binary image.* Apply a perspective transform to rectify binary image ("birds-eye view").* Detect lane pixels and fit to find the lane boundary.* Determine the curvature of the lane and vehicle position with respect to center.* Warp the detected lane boundaries back onto the original image.* Output visual display of the lane boundaries and numerical estimation of lane curvature and vehicle position.--- Camera calibration using chessboard function<jupyter_code>import numpy as np
import cv2
import glob
import matplotlib.pyplot as plt
%matplotlib qt

def calibratePinhole(chessboard_row, chessboard_col, filePaths):
    # prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
    objp = np.zeros((chessboard_row*chessboard_col,3), np.float32)
    objp[:,:2] = np.mgrid[0:chessboard_col,0:chessboard_row].T.reshape(-1,2)
    
    # Arrays to store object points and image points from all the images.
    objpoints = [] # 3d points in real world space
    imgpoints = [] # 2d points in image plane.
    
    # Make a list of calibration images
    images = glob.glob(filePaths)
    
    # Step through the list and search for chessboard corners
    for fname in images:
        img = cv2.imread(fname)
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        
        # Find the chessboard corners
        ret, corners = cv2.findChessboardCorners(gray, (chessboard_col,chessboard_row),None)
        
        # If found, add object points, image points
        if ret == True:
            objpoints.append(objp)
            imgpoints.append(corners)
    
    # Calibrate
    ret_calib, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img.shape[1::-1], None, None)
    
    # Visualization
    for fname in images:
        img = cv2.imread(fname)
        
        # Undistort
        undist = cv2.undistort(img, mtx, dist, None, mtx)
        
        # Draw and display the corners
        #undist = cv2.drawChessboardCorners(undist, (9,6), corners, ret)
        cv2.imshow('undist',undist)
        cv2.waitKey(500)
    
    cv2.destroyAllWindows()
    return mtx, dist<jupyter_output><empty_output><jupyter_text>Math Utility<jupyter_code>import numpy as np
class Combination:
    # arr[] ---> Input Array
    # data[] ---> Temporary array to store current combination
    # start & end ---> Staring and Ending indexes in arr[]
    # index ---> Current index in data[]
    # r ---> Size of a combination to be printed */
    def combinationUtil(self, arr, data, start, end, index, r):
        # Current combination is ready to be printed, print it
        if (index == r):
            temp = []
            for j in range(0,r):
                temp.append(data[j])
            self.temp.append(temp)
            return
        
        # replace index with all possible elements. The condition 
        # "end-i+1 >= r-index" makes sure that including one element 
        # at index will make a combination with remaining elements 
        # at remaining positions
        i = int(start)
        while (i <= end and end - i + 1 >= r - index):
            data[index] = arr[i];
            self.combinationUtil(arr, data, i + 1, end, index + 1, r);
            i+=1
    
    # The main function that prints all combinations of size r 
    # in arr[] of size n. This function mainly uses combinationUtil()
    def createIndexList(self, size, r):
        arr = list(range(0, size))
        self.temp = []
        
        # A temporary array to store all combination one by one 
        data = [0] * r;
        
        # Print all combination using temprary array 'data[]' 
        self.combinationUtil(arr, data, 0, len(arr) - 1, 0, r)
        return self.temp

def createPolynomial(point1,point2,point3):
    a = (point1[0] * (point3[1] - point2[1]) + point2[0] * (point1[1] - point3[1]) + point3[0] * (point2[1] - point1[1])) / ((point1[0] - point2[0])*(point1[0] - point3[0])*(point2[0] - point3[0]))
    b = (point2[1] - point1[1]) / (point2[0] - point1[0]) - a * (point1[0] + point2[0])
    c = point1[1] - a * point1[0] * point1[0] - b * point1[0]
    return a,b,c

def minDistanceToPoly(a,b,c,point):
    n3 = 4 * a * a
    n2 = 4 * a * b + 2 * a * b
    n1 = 4 * a * c - 4 * a * point[1] + 2 * b * b + 2
    n0 = 2 * b * c - 2 * point[0] - 2 * b * point[1]
    roots_of_coeff = np.roots([n3,n2,n1,n0])
    idx_no_complex = np.argwhere(np.iscomplex(roots_of_coeff) == False)
    if(len(idx_no_complex) == 0):
        raise ValueError('No x found')
        return
    else:
        x = np.asscalar(roots_of_coeff[idx_no_complex[0]].real)
        y = a * x * x + b * x + c
        return np.linalg.norm([(x - point[0]),(y - point[1])])

def angleBetweenVectors(vec1,vec2):
    dot = vec1[0]*vec2[0] + vec1[1]*vec2[1]      # dot product
    det = vec1[0]*vec2[1] - vec1[1]*vec2[0]      # determinant
    return math.atan2(det, dot)  # atan2(y, x) or atan2(sin, cos)

# Test
combinator = Combination()
ret = combinator.createIndexList(5,3)
print(ret)

a,b,c = createPolynomial((44,55),(11,22),(99,88))
print(55 - (a * 44 * 44 + b * 44 + c))
print(22 - (a * 11 * 11 + b * 11 + c))
print(88 - (a * 99 * 99 + b * 99 + c))

print(minDistanceToPoly(a,b,c,(99,88)))
print(minDistanceToPoly(a,b,c,(0,0)))<jupyter_output>[[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 3], [0, 2, 4], [0, 3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
0.0
3.552713678800501e-15
0.0
0.0
5.445361304156117<jupyter_text>RANSAC<jupyter_code>import math

def isCurveExtreme(a,b,c):
    if(a == 0.0):
        return False
    xAtPeak = (-b)/(2 * a)
    yAtPeak = a * xAtPeak * xAtPeak + b * xAtPeak + c
    
    diffFromPeak = 100.0
    xDiff = xAtPeak + diffFromPeak
    yDiff = a * xDiff * xDiff + b * xDiff + c
    return abs(yDiff - yAtPeak) >= abs(diffFromPeak)

def checkWindowContinuity(pointList, window_height, maxAngleInDegree):
    if(len(pointList) < 3):
        return True
    sortedByLevel = sorted(pointList, key=lambda x: x[0], reverse=True)
    lastX = sortedByLevel[1][0] - sortedByLevel[0][0]
    lastY = sortedByLevel[1][1] - sortedByLevel[0][1]
    norm_ = math.sqrt(lastX*lastX+lastY*lastY)
    lastX /= norm_
    lastY /= norm_
    for i in range(2,len(pointList)):
        x = sortedByLevel[i][0] - sortedByLevel[i-1][0]
        y = sortedByLevel[i][1] - sortedByLevel[i-1][1]
        norm_ = math.sqrt(x*x+y*y)
        level = abs(x/window_height)
        x /= norm_
        y /= norm_
        angleInDegree = abs(angleBetweenVectors((lastX,lastY),(x,y)) / math.pi * 180.0)
        if(angleInDegree > maxAngleInDegree):
            return False
        lastX = x
        lastY = y
    return True

def getInliers(pointList,threshold):
    combinator = Combination()
    if(len(pointList) < 3):
        return pointList
    indexList = combinator.createIndexList(len(pointList),3)
    best_inliers = []
    for indexes in indexList:
        inliers = [pointList[indexes[0]],pointList[indexes[1]],pointList[indexes[2]]]
        a,b,c = createPolynomial(inliers[0],inliers[1],inliers[2])
        if isCurveExtreme(a,b,c) == False: # coefficients check
            for i in range(0,len(pointList)):
                if i not in indexes:
                    minDistance = minDistanceToPoly(a,b,c,pointList[i])
                    if(minDistance < threshold):
                        inliers.append(pointList[i])
        if(len(inliers) > len(best_inliers)):
            if(checkWindowContinuity(inliers, 80, 51) == True):
                best_inliers = inliers
                if(len(best_inliers) == len(pointList)):
                    return best_inliers
    return best_inliers<jupyter_output><empty_output><jupyter_text>Image Processing<jupyter_code>def mask_threshold(img, thresh):
        # 5) Create a binary mask where direction thresholds are met
        binary_output = np.zeros_like(img)
        binary_output[(img >= thresh[0]) & (img <= thresh[1])] = 1
        # 6) Return this mask as your binary_output image
        return binary_output

def convertTo8bit(abs_img,max_value):
    res = np.uint8(255*abs_img/max_value)
    return res

def abs_sobel_calculate(gray, orient='x', kernel_size=None):
    # Apply the following steps to img
    # 2) Take the derivative in x or y given orient = 'x' or 'y'
    if(orient=='x'):
        if(kernel_size==None):
            sobel = cv2.Sobel(gray, cv2.CV_64F, 1, 0)
        else:
            sobel = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=kernel_size)
    elif(orient=='y'):
        if(kernel_size==None):
            sobel = cv2.Sobel(gray, cv2.CV_64F, 0, 1)
        else:
            sobel = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=kernel_size)
    else:
        raise Exception('Unknown orientation')
    # 3) Take the absolute value of the derivative or gradient
    abs_sobel = np.absolute(sobel)
    return abs_sobel

def get_binary_warped(undist_RGB):
        HSV = cv2.cvtColor(undist_RGB, cv2.COLOR_RGB2HSV)
        H = HSV[:,:,0]
        S = HSV[:,:,1]
        V = HSV[:,:,2]
        H_masked = mask_threshold(H, (20, 255))
        S_masked = mask_threshold(S, (0, 80))
        V_masked = mask_threshold(V, (200, 255))
        HSV_white_masked = np.zeros_like(H_masked)
        HSV_white_masked[(H_masked == 1) & (S_masked == 1) & (V_masked == 1)] = 1
        
        Luv = cv2.cvtColor(undist_RGB, cv2.COLOR_RGB2Luv)
        L = Luv[:,:,0]
        L_masked = mask_threshold(L, (225, 255))
        
        white_masked = np.zeros_like(H_masked)
        white_masked[(HSV_white_masked == 1) & (L_masked == 1)] = 1
        white_warped = convertTo8bit(white_masked,1)
        
        H_masked = mask_threshold(H, (0, 40))
        S_masked = mask_threshold(S, (80, 255))
        V_masked = mask_threshold(V, (200, 255))
        HSV_yellow_masked = np.zeros_like(H_masked)
        HSV_yellow_masked[(H_masked == 1) & (S_masked == 1) & (V_masked == 1)] = 1
        
        Lab = cv2.cvtColor(undist_RGB, cv2.COLOR_RGB2Lab)
        b = Lab[:,:,2]
        b_masked = mask_threshold(b, (155, 200))
        
        yellow_masked = np.zeros_like(H_masked)
        yellow_masked[(HSV_yellow_masked == 1) & (b_masked == 1)] = 1
        yellow_masked[(HSV_yellow_masked == 1)] = 1
        yellow_warped = convertTo8bit(yellow_masked,1)
        
        combined_masked = np.zeros_like(H_masked)
        combined_masked[(white_masked == 1) | (yellow_masked == 1)] = 1
        combined_warped = convertTo8bit(combined_masked,1)
        
        hls = cv2.cvtColor(undist_RGB, cv2.COLOR_RGB2HLS)
        L = hls[:,:,1]
        S = hls[:,:,2]
        
        L_sobelx = abs_sobel_calculate(L, orient='x', kernel_size=9)
        L_sobely = abs_sobel_calculate(L, orient='y', kernel_size=9)
        L_sobel = np.sqrt(np.add(np.square(L_sobelx), np.square(L_sobely)))
        L_sobel = convertTo8bit(L_sobel,np.max(L_sobel))
        L_sobel = mask_threshold(L_sobel, (30, 150))
        L_warped = convertTo8bit(L_sobel,1)
        
        S_sobelx = abs_sobel_calculate(S, orient='x', kernel_size=9)
        S_sobely = abs_sobel_calculate(S, orient='y', kernel_size=9)
        S_sobel = np.sqrt(np.add(np.square(S_sobelx), np.square(S_sobely)))
        S_sobel = convertTo8bit(S_sobel,np.max(S_sobel))
        S_sobel = mask_threshold(S_sobel, (30, 150))
        S_warped = convertTo8bit(S_sobel,1)
        
        combined_sobel_masked = np.zeros_like(H_masked)
        combined_sobel_masked[(L_sobel == 1) | (S_sobel == 1)] = 1
        combined_sobel_warped = convertTo8bit(combined_sobel_masked,1)
        
        final_masked = np.zeros_like(H_masked)
        final_masked[(combined_masked == 1) | (combined_sobel_masked == 1)] = 1
        final_warped = convertTo8bit(final_masked,1)
        return final_warped<jupyter_output><empty_output><jupyter_text>Windows Finder<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
%matplotlib qt
import matplotlib.image as mpimg
import glob
import cv2

def window_mask(width, height, img_ref, x, y):
    output = np.zeros_like(img_ref)
    y_min = y - int(height/2)
    y_max = y + int(height/2)
    x_min = x - int(width/2)
    x_max = x + int(width/2)
    output[int(y_min):int(y_max),int(x_min):int(x_max)] = 1
    return output

def find_windows(binary_warped, window_height, pointsize_threshold, diff_center, window_width):
    if(len(binary_warped.shape) > 2):
        raise ValueError('Input must be in grayscale')
    midpoint = int(binary_warped.shape[1]/2)
    y_min = binary_warped.shape[0] - window_height
    
    x_collection_left = []
    x_collection_right = []
    
    while(y_min >= 0):
        histogram = np.sum(binary_warped[y_min:(y_min+window_height),:], axis=0)
        # left
        x_base_left = np.argmax(histogram[:midpoint])
        pointsize_left = np.max(histogram[:midpoint])
        if(pointsize_left >= pointsize_threshold):
            midpoint = x_base_left + diff_center
            x_collection_left.append((y_min+int(window_height/2),x_base_left))
        # right
        x_base_right = np.argmax(histogram[midpoint:]) + midpoint
        pointsize_right = np.max(histogram[midpoint:])
        if(pointsize_right >= pointsize_threshold):
            midpoint = x_base_right - diff_center
            x_collection_right.append((y_min+int(window_height/2),x_base_right))
        
        y_min = y_min-window_height
    
    return x_collection_left, x_collection_right

def fit_poly(left_points, right_points):
    left_points_array = np.asarray(left_points)
    right_points_array = np.asarray(right_points)
    if((len(left_points_array.shape) != 2) or  (len(right_points_array.shape) != 2)):
        raise ValueError('Something is not right')
    elif((left_points_array.shape[1] != 2) or  (right_points_array.shape[1] != 2)):
        raise ValueError('Something is really not right')
     ### TO-DO: Fit a second order polynomial to each with np.polyfit() ###
    left_fit = np.polyfit(left_points_array[:,0], left_points_array[:,1], 2)
    right_fit = np.polyfit(right_points_array[:,0], right_points_array[:,1], 2)
    return left_fit, right_fit

# test
#user
#level = 9
#pointsize_threshold = 2000
#window_width = 50

#img = cv2.imread('../output_images/3_final.jpg')
##img = cv2.imread('../filter_test/white_yellow_combined.jpg')
#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#ori_img = img.copy()
#binary_warped = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#print(binary_warped.shape)

#x_collection_left, x_collection_right = find_windows(binary_warped, int(binary_warped.shape[0]/level), pointsize_threshold, 350, window_width)
#print(x_collection_left)
#print(x_collection_right)

#for x_left in x_collection_left:
#    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_left[1],x_left[0])
#    # Add graphic points from window mask here to total pixels found 
#    img[((mask == 1)) ] = (255,0,0)
#for x_right in x_collection_right:
#    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_right[1],x_right[0])
#    # Add graphic points from window mask here to total pixels found 
#    img[((mask == 1)) ] = (255,0,0)

#inliers_left = getInliers(x_collection_left, 20)
#inliers_right = getInliers(x_collection_right, 20)

#for x_left in inliers_left:
#    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_left[1],x_left[0])
#    # Add graphic points from window mask here to total pixels found 
#    img[((mask == 1)) ] = (0,255,0)
#for x_right in inliers_right:
#    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_right[1],x_right[0])
#    # Add graphic points from window mask here to total pixels found 
#    img[((mask == 1)) ] = (0,0,255)

#left_fit, right_fit = fit_poly(inliers_left, inliers_right)
def visualizePoly(img_shape, left_fit, right_fit):
    # Generate x and y values for plotting
    ploty = np.linspace(0, img_shape[0]-1, img_shape[0])
    ### TO-DO: Calc both polynomials using ploty, left_fit and right_fit ###
    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]
    
    return left_fitx, right_fitx, ploty

def visualize(binary_warped, left_fitx, right_fitx, ploty):
    margin = 100
    
    ## Visualization ##
    # Create an image to draw on and an image to show the selection window
    out_img = np.dstack((binary_warped, binary_warped, binary_warped))
    window_img = np.zeros_like(out_img)

    # Generate a polygon to illustrate the search window area
    # And recast the x and y points into usable format for cv2.fillPoly()
    left_line_window1 = np.array([np.transpose(np.vstack([left_fitx-margin, ploty]))])
    left_line_window2 = np.array([np.flipud(np.transpose(np.vstack([left_fitx+margin, 
                              ploty])))])
    left_line_pts = np.hstack((left_line_window1, left_line_window2))
    right_line_window1 = np.array([np.transpose(np.vstack([right_fitx-margin, ploty]))])
    right_line_window2 = np.array([np.flipud(np.transpose(np.vstack([right_fitx+margin, 
                              ploty])))])
    right_line_pts = np.hstack((right_line_window1, right_line_window2))

    # Draw the lane onto the warped blank image
    cv2.fillPoly(window_img, np.int_([left_line_pts]), (0,255, 0))
    cv2.fillPoly(window_img, np.int_([right_line_pts]), (0,255, 0))
    result = cv2.addWeighted(out_img, 1, window_img, 0.3, 0)
    ## End visualization steps ##
    
    return result

# test
#left_fitx, right_fitx, ploty = visualizePoly(binary_warped.shape, left_fit, right_fit)
#color_warp = visualize(binary_warped,left_fitx,right_fitx,ploty)
## Display the final results
#plt.figure(1)
#plt.title('masked image')
#plt.imshow(ori_img)
#plt.figure(2)
#plt.title('windowing result')
#plt.imshow(img)
#plt.figure(3)
#plt.title('polynomial fit result')
## Plot the polynomial lines onto the image
#plt.plot(left_fitx, ploty, color='yellow')
#plt.plot(right_fitx, ploty, color='yellow')
#plt.imshow(color_warp)
#plt.show()<jupyter_output><empty_output><jupyter_text>Visualization<jupyter_code>def overlay_lines(ori_undist,binary_warped,left_fitx,right_fitx,ploty):
    # Create an image to draw the lines on
    warp_zero = np.zeros_like(binary_warped).astype(np.uint8)
    color_warp = np.dstack((warp_zero, warp_zero, warp_zero))
    
    # 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.fillPoly(color_warp, np.int_([pts]), (0,255, 0))
    
    # Warp the blank back to original image space using inverse perspective matrix (Minv)
    newwarp = cv2.warpPerspective(color_warp, Minv, (binary_warped.shape[1], binary_warped.shape[0])) 
    # Combine the result with the original image
    result = cv2.addWeighted(ori_undist, 1, newwarp, 0.3, 0)
    return result<jupyter_output><empty_output><jupyter_text>Measurement<jupyter_code>def measure_curvature(left_fitx,right_fitx,ploty,xm_per_pix,ym_per_pix):
    # Fit a second order polynomial to pixel positions in each fake lane line
    ##### TO-DO: Fit new polynomials to x,y in world space #####
    ##### Utilize `ym_per_pix` & `xm_per_pix` here #####
    left_fit_cr = np.polyfit(ploty*ym_per_pix, left_fitx*xm_per_pix, 2)
    right_fit_cr = np.polyfit(ploty*ym_per_pix, right_fitx*xm_per_pix, 2)
    
    # Define y-value where we want radius of curvature
    # We'll choose the maximum y-value, corresponding to the bottom of the image
    y_eval = np.max(ploty)
    
    ##### TO-DO: Implement the calculation of R_curve (radius of curvature) #####
    left_curverad = (1+(2*left_fit_cr[0]*y_eval*ym_per_pix+left_fit_cr[1])**2)**(3/2)/np.abs(2*left_fit_cr[0])  ## Implement the calculation of the left line here
    right_curverad = (1+(2*right_fit_cr[0]*y_eval*ym_per_pix+right_fit_cr[1])**2)**(3/2)/np.abs(2*right_fit_cr[0])  ## Implement the calculation of the right line here
    
    return left_curverad,right_curverad<jupyter_output><empty_output><jupyter_text>Pipeline<jupyter_code>def process_image(image):
    # NOTE: The output you return should be a color image (3 channel) for processing video below
    # TODO: put your pipeline here,
    # you should return the final output (image where lines are drawn on lanes)
    global left_fit
    global right_fit
    
    unwrapped = cv2.undistort(image, mtx, dist, None, mtx)
    undist = cv2.warpPerspective(unwrapped, M, unwrapped.shape[1::-1], flags=cv2.INTER_LINEAR)
    
    # image processing
    binary_warped = get_binary_warped(undist)
    window_height = int(binary_warped.shape[0]/level)
    
    # windowing
    x_collection_left, x_collection_right = find_windows(binary_warped, window_height, pointsize_threshold, int(bottom_diff/2), window_width)
    if((len(x_collection_left) == 0) or (len(x_collection_right) == 0)):
        raise Exception('No windows')
    
    # identify reliability of bottom window
    max_left = max(x_collection_left, key=lambda x: x[0])
    max_right = max(x_collection_right, key=lambda x: x[0])
    if((max_left[0] == max_right[0]) and (len(left_fit) > 0)):
        if(max_left[0] == (binary_warped.shape[0] - int(window_height/2))):
            if((max_right[1] - max_left[1]) < (bottom_diff - 100)):
                minDistanceLeft = minDistanceToPoly(left_fit[0],left_fit[1],left_fit[2],max_left)
                minDistanceRight = minDistanceToPoly(right_fit[0],right_fit[1],right_fit[2],max_right)
                # if bottom window not reliable, remove it
                if(minDistanceLeft > minDistanceRight):
                    x_collection_left.remove(max_left)
                else:
                    x_collection_right.remove(max_right)
    
    # get inliers with RANSAC
    inliers_left = getInliers(x_collection_left, ransac_threshold)
    inliers_right = getInliers(x_collection_right, ransac_threshold)
    
    if((len(inliers_left) == 0) or (len(inliers_right) == 0)):
        raise Exception('Filter is too strong')
    
    # calculate polynomial only from inliers
    left_fit, right_fit = fit_poly(inliers_left, inliers_right)
    
    # for visualization
    left_fitx, right_fitx, ploty = visualizePoly(binary_warped.shape, left_fit, right_fit)
    
    # test
    #color_warp = visualize(binary_warped,left_fitx,right_fitx,ploty)
    #for x_left in x_collection_left:
    #    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_left[1],x_left[0])
    #    # Add graphic points from window mask here to total pixels found 
    #    color_warp[((mask == 1)) ] = (255,0,0)
    #for x_right in x_collection_right:
    #    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_right[1],x_right[0])
    #    # Add graphic points from window mask here to total pixels found 
    #    color_warp[((mask == 1)) ] = (255,0,0)
    #
    #for x_left in inliers_left:
    #    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_left[1],x_left[0])
    #    # Add graphic points from window mask here to total pixels found 
    #    color_warp[((mask == 1)) ] = (0,255,0)
    #for x_right in inliers_right:
    #    mask = window_mask(window_width,int(binary_warped.shape[0]/level),binary_warped,x_right[1],x_right[0])
    #    # Add graphic points from window mask here to total pixels found 
    #    color_warp[((mask == 1)) ] = (0,0,255)
    
    # Define conversions in x and y from pixels space to meters
    ym_per_pix = 30/float(binary_warped.shape[0]) # meters per pixel in y dimension
    distance_right_left_pix = float(right_fitx[-1] - left_fitx[-1])
    xm_per_pix = 3.7/distance_right_left_pix # meters per pixel in x dimension
    
    left_curverad,right_curverad = measure_curvature(left_fitx,right_fitx,ploty,xm_per_pix,ym_per_pix)
    #return cv2.addWeighted(undist, 1, color_warp, 0.3, 0)
    result = overlay_lines(unwrapped,binary_warped,left_fitx,right_fitx,ploty)
    cv2.putText(result, "Radius of Curvature = " + str(left_curverad) + " m",(50,120), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
    midpoint = distance_right_left_pix/2.0 + left_fitx[-1]
    distance_to_center = binary_warped.shape[1]/2.0 - midpoint
    cv2.putText(result, "Vehicle is " + str(distance_to_center * xm_per_pix * 100.0) + " cm to the center",(50,170), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
    return result
# windowing parameter
level = 9
pointsize_threshold = 100
window_width = 100
ransac_threshold = 20

# perspective transformation parameter
top_left = (557,475)
top_right = (729,475)
bottom_left = (253,697)
bottom_right = (1069,697)
src = np.float32([[top_left[0],top_left[1]],[top_right[0],top_right[1]],[bottom_left[0],bottom_left[1]],[bottom_right[0],bottom_right[1]]])

# Define conversions in x and y from pixels space to meters
dst = np.float32([[290,431],[990,431],[290,719],[990,719]]) # y = 24 pix/m, left to right = 700 pixel

# static variable, DO NOT CHANGE
M = cv2.getPerspectiveTransform(src,dst)
Minv = cv2.getPerspectiveTransform(dst,src)
bottom_diff = (dst[3] - dst[2])[0]
left_fit = []
right_fit = []
# Import everything needed to edit/save/watch video clips
from moviepy.editor import VideoFileClip
from IPython.display import HTML
mtx, dist = calibratePinhole(6, 9, '../camera_cal/calibration*.jpg')

fileName = "project_video.mp4"
white_output = "../test_videos_output/" + fileName
## To speed up the testing process you may want to try your pipeline on a shorter subclip of the video
## To do so add .subclip(start_second,end_second) to the end of the line below
## Where start_second and end_second are integer values representing the start and end of the subclip
## You may also uncomment the following line for a subclip of the first 5 seconds
##clip1 = VideoFileClip("test_videos/solidWhiteRight.mp4").subclip(0,5)
clip1 = VideoFileClip("../" + fileName)
white_clip = clip1.fl_image(process_image) #NOTE: this function expects color images!!
%time white_clip.write_videofile(white_output, audio=False)
#test, ignore this
import os
mtx, dist = calibratePinhole(6, 9, '../camera_cal/calibration*.jpg')
folderName = "../test_images/"
test_images = os.listdir(folderName)
for fileName in test_images:
    fileName_without = fileName.split(".")
    print(fileName)
    testOut_RGB = process_image(mpimg.imread(folderName + fileName))
    testOut = cv2.cvtColor(testOut_RGB, cv2.COLOR_RGB2BGR)
    cv2.imwrite("../output_images/" + fileName_without[0] + "_binary." + fileName_without[1], testOut)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12533313591945514, 'fraction_numerical': 0.03138880663310631, 'mean_word_length': 3.49235118057865, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '420543', 'license': 'MIT', 'n_tokens_mistral': 10163, 'n_tokens_neox': 9689, 'n_words': 2110, 'path': 'examples/example.ipynb', 'repo_name': 'derzaarsad/advanced_lane_finding', 'size': '27016'}