<jupyter_start><jupyter_text>Lane curvature and position<jupyter_code>import numpy as np
import cv2
import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib qt
from pathlib import Path
import os
import pipeline as pp<jupyter_output><empty_output><jupyter_text>Lane curvatureTo obtain an approximation of the pixel to meter ratio, I used the straight image 1, then apply an eagle eye view and visually fit a square from lane line to lane line, and between a dash-line. Knowing that the standard lane line has width of 3.7m and the standard dash line 3m. I computed an approximated ratio.<jupyter_code># test pipeline implementation
straight_lines1_file =   "../test_images/straight_lines1.jpg"


straight_lines1 = mpimg.imread(straight_lines1_file)

straight_lines1_warped = pp.eagle_eye(straight_lines1)

f1 = plt.figure(0)
plt.clf()
pts = np.array(
    [[270, 590],
     [270, 555],
     [1040, 555],
     [1040, 590]], np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(straight_lines1_warped,[pts],True,(0,255,255), 2)
plt.imshow(straight_lines1_warped)
f1.savefig("../output_images/lane_curvature_and_position/fitting.jpg")

ym_per_pix = 3 / (590 - 555) # dashline lengh / pixels in dashline
xm_per_pix = 3.7 / (1040 - 270) # lane width / pixel in lane
def fit_to_real_space(left_fit, right_fit, ym_per_pix, xm_per_pix):
    '''
    tranforms the fit from pixel space to real world space
    '''
    left_fit_real = np.zeros_like(left_fit)
    right_fit_real = np.zeros_like(right_fit)

    left_fit_real[0] = xm_per_pix * left_fit[0] / ym_per_pix**2
    left_fit_real[1] = xm_per_pix * left_fit[1] / ym_per_pix
    left_fit_real[2] = xm_per_pix * left_fit[2]

    right_fit_real[0] = xm_per_pix * right_fit[0] / ym_per_pix**2
    right_fit_real[1] = xm_per_pix * right_fit[1] / ym_per_pix
    right_fit_real[2] = xm_per_pix * right_fit[2]

    return left_fit_real, right_fit_real

def measure_curvature(ploty, left_fit, right_fit):
    '''
    Calculates the curvature of polynomial functions in the given dimensions.
    '''
    # 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)
    
    A_left = left_fit[0]
    B_left = left_fit[1]
    A_right = right_fit[0]
    B_right = right_fit[1]
    
    # Calculation of R_curve (radius of curvature)
    left_curverad = np.power(1  + np.power(2*A_left*y_eval + B_left, 2), 1.5) / (2 * np.abs(A_left))
    right_curverad = np.power(1  + np.power(2*A_right*y_eval + B_right, 2), 1.5) / (2 * np.abs(A_right))
    
    return left_curverad, right_curverad

# Make a list of calibration images
images = glob.glob('../test_images/*.jpg')

# Making output directory
output_dir = "../output_images/lane_curvature/"
Path(output_dir).mkdir(parents=True, exist_ok=True)

i = 1
for fname in images:
    # original
    img = mpimg.imread(fname)
    f = plt.figure(i)
    i = i + 1
    plt.imshow(img)

    # undistorted
    img_undist = pp.undistort_image(img)

    # bitmap with streigh guides
    bitmap = pp.threshold(img_undist)

    # eagle view with streigh guides
    img_eagle_eye = pp.eagle_eye(bitmap)

    x_half = int(img_eagle_eye.shape[0] / 2)
    y_half = int(img_eagle_eye.shape[1] / 2)
    bottom_half = img_eagle_eye[x_half:, :]

    # computing poly_fit using fit_poly in pipeline
    leftx, lefty, rightx, righty = pp.find_lane_pixels_window(bottom_half, nwindows=10, margin=100, minpix=40)
    left_fit, right_fit, left_fitx, right_fitx, ploty = pp.fit_poly(bottom_half.shape, leftx, lefty, rightx, righty)

    # tranfomation to real space
    left_fit_real, right_fit_real = fit_to_real_space(left_fit, right_fit, ym_per_pix, xm_per_pix)
    left_fitx_real = left_fitx * xm_per_pix
    right_fitx_real = right_fitx * xm_per_pix
    ploty_real = ploty * ym_per_pix

    # testing the transformation
    left_fitx_real_test = left_fit_real[0] * ploty_real**2 + left_fit_real[1] * ploty_real + left_fit_real[2]  

    # these two should be equivalent 
    print("left_fitx_computed=", left_fitx_real_test[:10])
    print("left_fitx_scaled=", left_fitx_real[:10])

    # computing curvature
    left_curverad, right_curverad = measure_curvature(ploty_real, left_fit_real, right_fit_real)
    print("left_curverad=", left_curverad)
    print("right_curverad=", right_curverad)

    plt.title("Left curve radious=" + "{:.2f}".format(left_curverad) + " right curve radious=" + "{:.2f}".format(right_curverad))

    f.savefig(output_dir + os.path.basename(fname))<jupyter_output>left_fitx_computed= [1.45324062 1.45297902 1.45271707 1.45245478 1.45219213 1.45192914
 1.4516658  1.4514021  1.45113806 1.45087367]
left_fitx_scaled= [1.45324062 1.45297902 1.45271707 1.45245478 1.45219213 1.45192914
 1.4516658  1.4514021  1.45113806 1.45087367]
left_curverad= 21034.47974650782
right_curverad= 1320.7653451733293
left_fitx_computed= [1.3991459  1.39904857 1.39895142 1.39885447 1.39875771 1.39866115
 1.39856478 1.39846861 1.39837262 1.39827683]
left_fitx_scaled= [1.3991459  1.39904857 1.39895142 1.39885447 1.39875771 1.39866115
 1.39856478 1.39846861 1.39837262 1.39827683]
left_curverad= 37944.32784694786
right_curverad= 2793.6119653067053
left_fitx_computed= [2.36404136 2.358141   2.35226052 2.34639989 2.34055913 2.33473823
 2.3289372  2.32315603 2.31739472 2.31165328]
left_fitx_scaled= [2.36404136 2.358141   2.35226052 2.34639989 2.34055913 2.33473823
 2.3289372  2.32315603 2.31739472 2.31165328]
left_curverad= 369.9835590042633
right_curverad= 343.1931807509366
left_[...]<jupyter_text>The values seem to be reasonable. The 1 KM was not obtain but the values are in magnitude range of the problem and it behaves as expected in most of the cases. In strait lines being a big value for example:![Lanes Image](../output_images/lane_curvature/straight_lines2.jpg)And for sharp curves havin a smaller value:![Lanes Image](../output_images/lane_curvature/test3.jpg)There are some cases in which the 2 lanes show different curvature, specially if there was a lane with hard conditions as the following one in which there is a shadow and a change of color in the road. Consequently there is still room for improvement or at least selection of the most accurate value in between this 2.  Car positionTo approximate the car position with respect to the lane I will assume the camera is at the center of the car and aligned with the lane. So I will compute the lane closest to the car and make an interpolation using the lane width od 3.7m<jupyter_code># Make a list of calibration images
images = glob.glob('../test_images/*.jpg')

# Making output directory
output_dir = "../output_images/lane_curvature/"
Path(output_dir).mkdir(parents=True, exist_ok=True)

i = 1
for fname in images:
    # original
    img = mpimg.imread(fname)
    f = plt.figure(i)
    i = i + 1
    plt.imshow(img)

    # undistorted
    img_undist = pp.undistort_image(img)

    # bitmap with streigh guides
    bitmap = pp.threshold(img_undist)

    # eagle view with streigh guides
    img_eagle_eye = pp.eagle_eye(bitmap)

    x_half = int(img_eagle_eye.shape[1] / 2)
    y_half = int(img_eagle_eye.shape[0] / 2)
    bottom_half = img_eagle_eye[y_half:, :]

    # computing poly_fit using fit_poly in pipeline
    leftx, lefty, rightx, righty = pp.find_lane_pixels_window(bottom_half, nwindows=10, margin=100, minpix=40)
    left_fit, right_fit, left_fitx, right_fitx, ploty = pp.fit_poly(bottom_half.shape, leftx, lefty, rightx, righty)

    # tranfomation to real space
    left_fit_real, right_fit_real = pp.fit_to_real_space(left_fit, right_fit)
    left_fitx_real = left_fitx * xm_per_pix
    right_fitx_real = right_fitx * xm_per_pix
    ploty_real = ploty * ym_per_pix

    y_bottom = np.max(ploty_real)
    left_lane_x_position = left_fit_real[0] * y_bottom**2 + left_fit_real[1] * y_bottom + left_fit_real[2] 
    right_lane_x_position = right_fit_real[0] * y_bottom**2 + right_fit_real[1] * y_bottom + right_fit_real[2] 
    middle_position = xm_per_pix * img_eagle_eye.shape[1] / 2

    position = middle_position - (right_lane_x_position + left_lane_x_position) / 2

    print(os.path.basename(fname) + " position=", position)
# Testing pipeline function

for fname in images:
    # original
    img = mpimg.imread(fname)
    f = plt.figure(i)
    i = i + 1
    plt.imshow(img)

    # undistorted
    img_undist = pp.undistort_image(img)

    # bitmap with streigh guides
    bitmap = pp.threshold(img_undist)

    # eagle view with streigh guides
    img_eagle_eye = pp.eagle_eye(bitmap)

    x_half = int(img_eagle_eye.shape[1] / 2)
    y_half = int(img_eagle_eye.shape[0] / 2)
    bottom_half = img_eagle_eye[y_half:, :]

    # computing poly_fit using fit_poly in pipeline
    leftx, lefty, rightx, righty = pp.find_lane_pixels_window(bottom_half, nwindows=10, margin=100, minpix=40)
    left_fit, right_fit, left_fitx, right_fitx, ploty = pp.fit_poly(bottom_half.shape, leftx, lefty, rightx, righty)

    # tranfomation to real space
    left_fit_real, right_fit_real = pp.fit_to_real_space(left_fit, right_fit)
    left_fitx_real = left_fitx * xm_per_pix
    right_fitx_real = right_fitx * xm_per_pix
    ploty_real = ploty * ym_per_pix

    position = pp.car_position(img, ploty_real, left_fit_real, right_fit_real)

    print(os.path.basename(fname) + " position=", position)<jupyter_output>straight_lines1.jpg position= -0.0113268710901675
straight_lines2.jpg position= -0.05342245693008252
test1.jpg position= -0.2785311194752227
test2.jpg position= -0.30466028780960386
test3.jpg position= -0.11703092147120842
test4.jpg position= -0.3305885839197269
test5.jpg position= -0.30595894316299566
test6.jpg position= -0.12495189163478138
{'fraction_non_alphanumeric': 0.09549753289473684, 'fraction_numerical': 0.09693667763157894, 'mean_word_length': 4.2961350027218295, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '408637', 'license': 'MIT', 'n_tokens_mistral': 4298, 'n_tokens_neox': 3690, 'n_words': 851, 'path': 'pipeline/lane_curvature_and_position.ipynb', 'repo_name': 'AnibalSiguenza/advance_line_finding', 'size': '9728'}