def canny_edge_detector(input, source, e):
    # creating folders if not created previously
    if not os.path.exists(PATH):
        os.makedirs(PATH)
    if not os.path.exists(PATH + input):
        os.makedirs(PATH + input)

    Image_after_filter, H1, W1 = GuassianFilter.gaussian_filtering(
        source)  # compute gaussian filter
    cv2.imwrite(PATH + input + "/gaussianblur.bmp",
                Image_after_filter)  # save gaussian image.

    x, y = SobelOperator.sobel(Image_after_filter, H1,
                               W1)  # find horizontal gradient
    cv2.imwrite(PATH + input + "/horizontalgradient.bmp",
                x)  # save horizontal gradient
    cv2.imwrite(PATH + input + "/verticalgradient.bmp",
                y)  # save vertical gradient

    # compute gradient magnitude and angle
    gradient_magnitude, gradient_angle = Thresholding.compute_magnitude_angle(
        x, y)
    cv2.imwrite(PATH + input + "/gradientmagnitude.bmp",
                gradient_magnitude)  # save gradient_magnitude

    # non maximuma supression on gradient magnitude.
    c = Thresholding.suppression(gradient_magnitude, gradient_angle)
    cv2.imwrite(PATH + input + "/nonmaximasuppression.bmp", c)

    e = Thresholding.doublethresholding(c, gradient_angle)
    cv2.imwrite(PATH + input + "/doublethresholding.bmp",
                e)  # save after doublethresholding
Пример #2
0
def process_image(img):
    # Loader.print_image(img)
    # print("[DEBUG] Showing VISUAL denoising algorithm comparison")
    # denoising_comparison(img)
    # print("[DEBUG] Showing HISTOGRAM denoising algorithm comparison")
    # denoising_comparison(img, True)

    # DENOISING IMAGE
    denoised_img = smooth.median_filter(img, 9)
    denoised_img = smooth.median_filter(denoised_img, 7)
    # PRINT DENOISED IMAGE AND HISTOGRAM
    #Loader.print_image(denoised_img)
    # Loader.hist_and_cumsum(denoised_img)

    # thresholding_comparison(denoised_img)
    th_img = thresh.apply_thresholding_algorithm(denoised_img,
                                                 thresh.THRESH_TRIANGLE)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 5))
    stretched = cv2.morphologyEx(th_img, cv2.MORPH_ERODE, kernel)
    back, front = thresh.get_regions(denoised_img, stretched)
    # Loader.hist_compare([back, front], ["Back", "Front"])
    #Loader.print_image(front)
    eq = Loader.equalization(front.astype("uint8"))
    eq = bright_and_contrast(eq, 2.8, 80)
    eq = smooth.gaussian(eq, 2.5)
    Loader.print_image(eq)
    # Loader.hist_and_cumsum(eq)

    # EDGE DETECTION
    #edgesFunctions(eq) # Comparison of different edge detection method
    edges = edg.laplacian_of_gaussian(eq, 2)
    Loader.print_image(edges)
    # Fill the cornea area with white pixels
    dilated = fill_cornea(edges)
    #Loader.print_image(dilated)
    #Calculate distances in the cornea-lens region
    #lineas = dw.find_vertical_lines(dilated)
    #diferencias,posiciones = dw.calculate_differences(lineas)
    #dw.draw_graph_distance(diferencias, posiciones)
    #output_image = dw.lines_image(lineas, img)
    # Surround the córnea area and lens edges with visible and thin line
    (i, contornos, jerarquia) = cv2.findContours(dilated, cv2.RETR_EXTERNAL,
                                                 cv2.CHAIN_APPROX_SIMPLE)
    cnts = []
    for c in contornos:
        if cv2.contourArea(c) < 1000:
            continue
        else:
            cnts.append(c)
    cv2.drawContours(img, cnts, -1, (0, 0, 255), 3)
    #Loader.print_image(img)
    return img
Пример #3
0
 def __init__(self):
     """ Init Application"""
     self.mtx, self.dist = loadCoefficients()
     self.imgSize = (720, 1280)
     # Define 4 source points
     self.src = np.float32([[250, self.imgSize[0] - 25], [575, 460],
                            [700, 460], [1150, self.imgSize[0] - 25]])
     # Define 4 destination points
     self.dst = np.float32([[320, self.imgSize[0] - 25], [320, 0], [960, 0],
                            [960, self.imgSize[0] - 25]])
     self.thresholding = Thresholding()
     self.undistort = undistortImage
     self.transform = warper
     self.laneLines = LaneLines()
     self.counter = 0
Пример #4
0
class FindLaneLines:
    """ This class is for parameter tunning.

    Attributes:
        ...
    """
    def __init__(self):
        """ Init Application"""
        self.calibration = CameraCalibration('camera_cal', 9, 6)
        self.thresholding = Thresholding()
        self.transform = PerspectiveTransformation()
        self.lanelines = LaneLines()

    def forward(self, img):
        out_img = np.copy(img)
        img = self.calibration.undistort(img)
        img = self.transform.forward(img)
        img = self.thresholding.forward(img)
        img = self.lanelines.forward(img)
        img = self.transform.backward(img)

        out_img = cv2.addWeighted(out_img, 1, img, 0.6, 0)
        out_img = self.lanelines.plot(out_img)
        return out_img

    def process_image(self, input_path, output_path):
        img = mpimg.imread(input_path)
        out_img = self.forward(img)
        mpimg.imsave(output_path, out_img)

    def process_video(self, input_path, output_path):
        clip = VideoFileClip(input_path)
        out_clip = clip.fl_image(self.forward)
        out_clip.write_videofile(output_path, audio=False)
Пример #5
0
 def __init__(self, master=None):
     """ Init Application"""
     super().__init__(master)
     self.master = master
     self.create_widgets()
     self.grid()
     self.filepath = ""
     self.image = None
     self.debug = True
     self.calibration = CameraCalibration('camera_cal', 9, 6)
     self.thresholding = Thresholding()
     self.transform = PerspectiveTransformation()
     self.lanelines = LaneLines(debug=self.debug)
     self.vidcap = None
     self.frames = []
     self.current_frameid = -1
Пример #6
0
def algomixerFunnel (algos, return_count, finalalgo, finalalgoDataframe, algoname='NewAlgo') : 
    # myAlgos = [ search_RGB, search_SIFT_BF ]
    # algomixerFunnel (myAlgos)
    start = time.time()

    algoResults = []
    algoTimes = []
    for algo in algos: 
        algoResult, algoTime = algo_selector (algo, return_count=return_count)
        algoResults.append(algoResult)
        algoTimes.append(algoTime)

    # generate candidates (short listing)
    filteredFeatureData = Thresholding.filter_candidates( algoResults, finalalgoDataframe)
    # run Final Algo (detection) 
    imagepredictions,searchtimesift = algo_selector_final(finalalgo,filteredFeatureData,return_count=return_count)

    # generate algo uniques: apply threshold for each Result (imagematches)     
    unique_final_list = []
    for Result in algoResults : 
        unique_final_list.append(Thresholding.autothreshold_knee(Result))

    # print (unique_final_list)
    # MERGE OPEARATION FROM ALL RESULTS 
    # algo uniques + final algo detections results 
    final_algo_List = Thresholding.imagepredictions_to_list(imagepredictions)
    
    toplist = unique_final_list.copy()
    # copy all commons from candidates threshold list to front (2 lists)
    toplist = [Thresholding.merge_results( toplist, False)]

    # Add final algo derivatives to toplist 
    toplist.append(final_algo_List)
    # merge lists of algo results: HSV Thresh, RGB Thresh, SIFT
    toplist = Thresholding.merge_results( toplist, False)

    t = time.time() - start

    # find accuracy and append to dict 
    a ,d, ind, cnt = accuracy.accuracy_from_list(q_path, toplist, 20 )
    print ('index F_'+algoname+': ', ind)
    row_dict['acc_'+ algoname] = a
    row_dict['index_'+ algoname] = ind
    row_dict['Count_'+ algoname] = cnt
    row_dict['quality_'+ algoname] = d
    row_dict['time_'+ algoname] = t
Пример #7
0
def algomixerAppend(algos, return_count, algoname='NewAlgo', write=False):
    # myAlgos = [ search_RGB, search_SIFT_BF ]
    # algomixerFunnel (myAlgos)
    start = time.time()

    algoResults = []
    algoTimes = []
    for algo in algos:
        thisResult, thisTime = algo_selector(algo, return_count=return_count)
        algoResults.append(thisResult)
        algoTimes.append(thisTime)

    # generate algo uniques: apply threshold for each Result (imagematches)
    unique_final_list = []
    for result in algoResults:
        if write:
            a, d, ind, cnt = accuracy.accuracy_matches(q_path, result,
                                                       ACCURRACY_RANGE)
            print(ind)
        unique_final_list.append(Thresholding.autothreshold_knee(result))

    # MERGE OPEARATION FROM ALL RESULTS
    # algo uniques + final algo detections results

    toplist = unique_final_list.copy()

    # retaining all the individual results as well (P.S: note difference from algomixerFunnel)
    for result in algoResults:
        toplist.append(Thresholding.imagepredictions_to_list(result))

    # merge lists of algo results and remove duplicates order[[commons], [algo1], [algo2]...]
    toplist = Thresholding.merge_results(toplist, False)

    t = time.time() - start

    # find accuracy and append to dict
    # a ,d, ind, cnt = accuracy.accuracy_from_list(q_path, toplist, ACCURRACY_RANGE)
    # print ('index F_'+algoname+': ', ind)

    # row_dict['acc_'+ algoname] = a
    # row_dict['index_'+ algoname] = ind
    # row_dict['Count_'+ algoname] = cnt
    # row_dict['quality_'+ algoname] = d
    # row_dict['time_'+ algoname] = t
    return toplist
Пример #8
0
class FindLaneLines:
    """ This class is for parameter tunning.

    Attributes:
        ...
    """
    def __init__(self):
        """ Init Application"""
        self.mtx, self.dist = loadCoefficients()
        self.imgSize = (720, 1280)
        # Define 4 source points
        self.src = np.float32([[250, self.imgSize[0] - 25], [575, 460],
                               [700, 460], [1150, self.imgSize[0] - 25]])
        # Define 4 destination points
        self.dst = np.float32([[320, self.imgSize[0] - 25], [320, 0], [960, 0],
                               [960, self.imgSize[0] - 25]])
        self.thresholding = Thresholding()
        self.undistort = undistortImage
        self.transform = warper
        self.laneLines = LaneLines()
        self.counter = 0

    def runPipeline(self, img):
        out_img = np.copy(img)

        img_undist = self.undistort(img, self.mtx, self.dist)
        #cv2.imwrite('output_images/undistorted.jpg', img_undist)
        img = self.thresholding.run(img_undist)
        #cv2.imwrite('output_images/thresholded.jpg', img)

        binaryWarped, M, invM = self.transform(img, self.src, self.dst)
        if self.counter == 0 or (self.counter >= 100
                                 and self.counter % 100 == 0):
            imgname = 'output_images/binary' + str(self.counter) + 'warped.jpg'
            cv2.imwrite(imgname, binaryWarped)
        self.laneLines.fit_polynomial(binaryWarped)
        if self.laneLines.leftLine.detected and self.laneLines.rightLine.detected:
            self.laneLines.measure_curvature_real(binaryWarped)
            out_img = self.laneLines.drawLane(img_undist, binaryWarped, invM)
            #cv2.imwrite('output_images/drawlanes.jpg', out_img)
            out_img = self.laneLines.drawData(out_img)
        self.counter += 1
        return out_img

    def processImage(self, input_path, output_path):
        img = cv2.imread(input_path)
        out_img = self.runPipeline(img)
        cv2.imwrite(output_path, out_img)

    def processVideo(self, input_path, output_path):
        clip = VideoFileClip(input_path)
        out_clip = clip.fl_image(self.runPipeline)
        out_clip.write_videofile(output_path, audio=False)
Пример #9
0
def thresholding_comparison(img):

    #Thresholding algoritms precalculation for comparison
    triangle = thresh.apply_thresholding_algorithm(img, thresh.THRESH_TRIANGLE)
    mean = thresh.apply_thresholding_algorithm(img, thresh.THRESH_MEAN)
    otsu = thresh.apply_thresholding_algorithm(img, thresh.THRESH_OTSU)
    yen = thresh.apply_thresholding_algorithm(img, thresh.THRESH_YEN)
    minimum = thresh.apply_thresholding_algorithm(img, thresh.THRESH_MIMIMUM)
    isodata = thresh.apply_thresholding_algorithm(img, thresh.THRESH_ISODATA)
    # li = thresh.apply_thresholding_algorithm(img, thresh.THRESH_LI)

    thresholded_imgs = [img, triangle, mean, otsu, yen, minimum, isodata]
    thresholded_titles = [
        "Original", "Triangle", "Mean", "Otsu", "Yen", "Minimum", "Isodata"
    ]
    Loader.hist_compare(thresholded_imgs, thresholded_titles)
Пример #10
0
def search_AlgoA ( candidates=100, verbose=False ): 
    toplist = []
    start = time.time()
    # run RGB
    imagematchesrgb , searchtimergb = ImageSearch_Algo_RGB.RGB_SEARCH_TREE (myRGBtree, mydataRGB, q_path, returnCount=candidates)
    # run HSV
    imagematcheshsv , searchtimehsv = ImageSearch_Algo_HSV.HSV_SEARCH_TREE ( myHSVtree, mydataHSV, q_path, returnCount=candidates)
    # create shortlist for SIFT 
    filteredSIFTData = Thresholding.filter_sift_candidates( [imagematcheshsv, imagematchesrgb], mydataSIFT)
    # run SIFT 
    imagepredictions , searchtimesift = ImageSearch_Algo_SIFT.SIFT_SEARCH_BF(filteredSIFTData, q_path, sift_features_limit=100 , lowe_ratio=LOWE_RATIO, predictions_count=SIFT_PREDICTIONS_COUNT)

    # threshold RGB 
    final_RGB_List = Thresholding.autothreshold_knee(imagematchesrgb)

    # thresold HSV 
    final_HSV_List = Thresholding.autothreshold_knee(imagematcheshsv)

    # MERGE OPEARATION FROM ALL RESULTS 
    # SIFT LIST 
    final_SIFT_List = Thresholding.imagepredictions_to_list(imagepredictions)
    
    # merge lists of algo results: HSV Thresh, RGB Thresh, SIFT
    toplist = Thresholding.merge_results([final_HSV_List, final_RGB_List, final_SIFT_List], False)
    
    # find accuracy and append to dict 
    a ,d, ind, cnt = accuracy.accuracy_from_list(q_path, toplist, 20 )
    t = time.time() - start
    row_dict['acc_algo_A'] = a
    row_dict['index_algo_A'] = ind
    row_dict['Count_algo_A'] = cnt
    row_dict['quality_algo_A'] = d
    row_dict['time_algo_A'] = t

    # run if verbose enabled; DEBUGGING
    if verbose: 

        print ('index FINAL AlgoA: ', ind)
        # append SIFT Results 
        a ,d, ind, cnt = accuracy.accuracy_matches(q_path, imagepredictions, 20 )
        print ('SIFT-A Accuracy =',  a, '%', '| Quality:', d )
        print ('SIFT-A Count', cnt, ' | position', ind)
        row_dict['acc_Algo_A_SIFT'] = a
        row_dict['index_Algo_A_SIFT'] = ind
        row_dict['Count_Algo_A_SIFT'] = cnt
        row_dict['quality_Algo_A_SIFT'] = d
        # row_dict['time_Algo_A_SIFT'] = searchtime
        # get current accurracy of RGB     
        a, d, ind, cnt = accuracy.accuracy_matches(q_path, imagematchesrgb, 20)
        print ('index RGB   : ', ind)
        # get thresholded accurracy of RGB     
        a ,d, ind, cnt = accuracy.accuracy_from_list(q_path, final_RGB_List, 20 )
        print ('index RGB Th:', ind)
        # update candidates RGB
        row_dict['index_Algo_A_cRGB'] = ind
        # get current accurracy for HSV
        a, d, ind, cnt = accuracy.accuracy_matches(q_path, imagematcheshsv, 20)
        print ('index HSV   : ', ind)
        # get thresholded accurracy for HSV 
        a ,d, ind, cnt = accuracy.accuracy_from_list(q_path, final_HSV_List, 20 )
        print ('index HSV Th: ', ind)
        # update candidates 
        row_dict['index_Algo_A_cHSV'] = ind


    return imagepredictions, t
Пример #11
0
    def algomixerFunnel(algos,
                        return_count,
                        finalalgo,
                        finalalgoDataframe,
                        algoname='NewAlgo',
                        write=False):
        '''
        algos [list]: list of candidare algos
        return_count (int) : number of candidates to be generated 
        finalalgo (str) : list of candidare algos
        finalalgoDataframe (pd.Dataframe): dataframe of the finalAlgo to be filtered and used 
        algoname (str)  : 'column name of datframe for the final reported accuracy, time etc.
        write (bool): True / False -> whether to report funnel accurracy, time before merge with thresholded candidates 
        '''

        # myAlgos = [ search_RGB, search_SIFT_BF ]
        # algomixerFunnel (myAlgos)
        start = time.time()

        algoResults = []
        algoTimes = []
        for algo in algos:
            algoResult, algoTime = algo_selector(algo,
                                                 return_count=return_count)
            algoResults.append(algoResult)
            algoTimes.append(algoTime)

        # generate candidates (short listing)
        filteredFeatureData = Thresholding.filter_candidates(
            algoResults, finalalgoDataframe)
        # run Final Algo (detection)
        imagepredictions, searchtimesift = algo_selector_final(
            finalalgo, filteredFeatureData, return_count=return_count)
        if write:
            # find accuracy and append to dict
            a, d, ind, cnt = accuracy.accuracy_matches(q_path,
                                                       imagepredictions,
                                                       ACCURRACY_RANGE)
            t = time.time() - start
            row_dict['acc_' + algoname + '_BM'] = a
            row_dict['index_' + algoname + '_BM'] = ind
            row_dict['Count_' + algoname + '_BM'] = cnt
            row_dict['quality_' + algoname + '_BM'] = d
            row_dict['time_' + algoname + '_BM'] = t

        # generate algo uniques: apply threshold for each Result (imagematches)
        unique_final_list = []
        for Result in algoResults:
            unique_final_list.append(Thresholding.autothreshold_knee(Result))

        # print (unique_final_list)
        # MERGE OPEARATION FROM ALL RESULTS
        # algo uniques + final algo detections results
        final_algo_List = Thresholding.imagepredictions_to_list(
            imagepredictions)

        toplist = unique_final_list.copy()
        # copy all commons from candidates threshold list to front (2 lists)
        toplist = [Thresholding.merge_results(toplist, False)]

        # Add final algo derivatives to toplist
        toplist.append(final_algo_List)
        # merge lists of algo results: HSV Thresh, RGB Thresh, SIFT
        toplist = Thresholding.merge_results(toplist, False)

        t = time.time() - start

        # find accuracy and append to dict
        a, d, ind, cnt = accuracy.accuracy_from_list(q_path, toplist,
                                                     ACCURRACY_RANGE)
        # print ('index F_'+algoname+': ', ind)
        row_dict['acc_' + algoname] = a
        row_dict['index_' + algoname] = ind
        row_dict['Count_' + algoname] = cnt
        row_dict['quality_' + algoname] = d
        row_dict['time_' + algoname] = t
Пример #12
0
 def __init__(self):
     """ Init Application"""
     self.calibration = CameraCalibration('camera_cal', 9, 6)
     self.thresholding = Thresholding()
     self.transform = PerspectiveTransformation()
     self.lanelines = LaneLines()
    print("[DEBUG] Load image from local sources")
    # img = Loader.load_image("test/th.jpeg")
    # Loader.print_image(stretched)
    # Loader.print_image(smoothed_thresholded)
    # Loader.print_image(front)

    for i in np.arange(1, 13):
        img = Loader.load_image("im" + i.__str__() + ".jpeg")
        print("Loaded image " + "im" + i.__str__() + ".jpeg")
        # DENOISING IMAGE
        denoised_img = smooth.median_filter(img, 9)
        denoised_img = smooth.median_filter(denoised_img, 7)

        # thresholding_comparison(denoised_img)
        th_img = thresh.apply_thresholding_algorithm(denoised_img,
                                                     thresh.THRESH_TRIANGLE)
        #Suavizamos los bordes marcados por la segmentacion
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 5))
        stretched = cv2.morphologyEx(th_img, cv2.MORPH_ERODE, kernel)
        smoothed_thresholded = smooth.max_filter(stretched, 5)
        #Obtenemos las areas correspondientes a la imagen original, despues del segmentado
        back, front = thresh.get_regions(denoised_img, stretched)

        IMAGE_TYPE_CLASSIFICATION = define_image_properties(
            smoothed_thresholded)
        if IMAGE_TYPE_CLASSIFICATION == "A":
            # RESOLUTION 1
            print("Executing custom resolution, mode 1")
            # EDGE DETECTION
            #eq = Loader.equalization(front.astype("uint8"))
            eq = Loader.bright_and_contrast(front.astype("uint8"), 1.0, 20)
Пример #14
0
 def load_parameters(self):
     load_params()
     self.thresholding = Thresholding()
     self.transform = PerspectiveTransformation()
     self.lanelines = LaneLines(debug=self.debug)
Пример #15
0
class Application(tk.Frame):
    """ This class is for parameter tunning.

    Attributes:
        ...
    """
    def __init__(self, master=None):
        """ Init Application"""
        super().__init__(master)
        self.master = master
        self.create_widgets()
        self.grid()
        self.filepath = ""
        self.image = None
        self.debug = True
        self.calibration = CameraCalibration('camera_cal', 9, 6)
        self.thresholding = Thresholding()
        self.transform = PerspectiveTransformation()
        self.lanelines = LaneLines(debug=self.debug)
        self.vidcap = None
        self.frames = []
        self.current_frameid = -1

    def create_widgets(self):
        self.winfo_toplevel().title("Parameter Tuning")

        self.hi_there = tk.Button(self,
                                  text="Load image",
                                  command=self.load_image)
        self.hi_there.grid(row=1)

        self.textbox = tk.Entry(self)
        self.textbox.insert(0, 'test_images/project_video_frame_1048.jpg')
        self.textbox.grid(row=0)

        self.save = tk.Button(self,
                              text="Save params",
                              command=self.save_parameters)
        self.save.grid(row=2)
        self.load = tk.Button(self,
                              text="Load params",
                              command=self.load_parameters)
        self.load.grid(row=3)

        self.quit = tk.Button(self,
                              text="Quit",
                              fg="red",
                              command=self.master.destroy)
        self.quit.grid(row=5)

        self.process_image_button = tk.Button(self,
                                              text="Process image",
                                              command=self.process_image)
        self.process_image_button.grid(row=1, column=1)

        self.process_video_button = tk.Button(self,
                                              text="Process video",
                                              command=self.process_video)
        self.process_video_button.grid(row=1, column=2)

        self.frame_textbox = tk.Entry(self)
        self.frame_textbox.grid(row=0, column=1)

        self.get_frame_button = tk.Button(self,
                                          text="Get frame from video",
                                          command=self.get_frame)
        self.get_frame_button.grid(row=2, column=1)

        self.save_frame_button = tk.Button(self,
                                           text="Save frame from video",
                                           command=self.save_frame)
        self.save_frame_button.grid(row=3, column=1)

        self.debug_button = tk.Button(self,
                                      text="Debug ON",
                                      command=self.toggle_debug)
        self.debug_button.grid(row=1, column=3)

    def load_image(self):
        self.current_frameid = -1
        self.filepath = self.textbox.get()
        self.image = cv2.imread(self.filepath)

        img = self.image
        cv2.imshow("original", img)

        self.thresholding.display(img)
        img = self.thresholding.forward(img)

        self.transform.display(img)
        img = self.transform.forward(img)

        self.lanelines.display(img)

    def forward(self, img):
        out_img = np.copy(img)
        img = self.calibration.undistort(img)
        img = self.thresholding.forward(img)
        img2 = np.dstack((img, img, img))
        img = self.transform.forward(img)
        img = self.lanelines.forward(img)
        img3 = img
        img = self.transform.backward(img)

        out_img = cv2.addWeighted(out_img, 1, img, 0.3, 0)
        out_img = self.lanelines.plot(out_img)
        if self.debug and self.current_frameid >= 0:
            cv2.putText(out_img,
                        str(self.current_frameid),
                        org=(700, 100),
                        fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                        fontScale=1,
                        color=(0, 0, 0),
                        thickness=2)
            self.current_frameid += 1
        return out_img

    def process_image(self):
        self.current_frameid = -1
        img = cv2.imread(self.textbox.get())
        out_img = self.forward(img)
        cv2.imshow("output", out_img)

    def process_video(self):
        self.current_frameid = 0
        self.filepath = self.textbox.get()
        clip = VideoFileClip(self.filepath)
        out_clip = clip.fl_image(self.forward)
        out_clip.write_videofile("output_videos/" + self.filepath, audio=False)

    def get_frame(self):
        path = self.textbox.get()
        frame_id = int(self.frame_textbox.get())
        if (path != self.filepath) or (self.vidcap is None):
            self.vidcap = cv2.VideoCapture(path)
            self.filepath = path
            self.frames = []

        if len(self.frames) > frame_id:
            cv2.imshow("Frame {}".format(frame_id), self.frames[frame_id])
            return

        success, image = self.vidcap.read()
        while success:
            self.frames.append(image)
            if len(self.frames) > frame_id:
                cv2.imshow("Frame {}".format(frame_id), self.frames[frame_id])
                return
            success, image = self.vidcap.read()

    def save_frame(self):
        path = self.textbox.get()
        frame_id = int(self.frame_textbox.get())

        l = path.rfind('/') + 1
        r = path.find('.')
        output_path = "test_images/" + path[l:r] + "_frame_{}.jpg".format(
            frame_id)
        self.get_frame()
        cv2.imwrite(output_path, self.frames[frame_id])

    def toggle_debug(self):
        self.debug = not self.debug
        if self.debug:
            self.debug_button.config(text="Debug ON")
        else:
            self.debug_button.config(text="Debug OFF")
        self.lanelines.debug = self.debug

    def save_parameters(self):
        self.thresholding.save_parameters()
        save_params()

    def load_parameters(self):
        load_params()
        self.thresholding = Thresholding()
        self.transform = PerspectiveTransformation()
        self.lanelines = LaneLines(debug=self.debug)