can you check this file for errors: import cv2
import numpy as np
import os
import sys
import matplotlib.pyplot as plt
import time
from glob import glob

def feature_extraction(method, image):
    if method == "SIFT":
        feature_extractor = cv2.SIFT_create()
    elif method == "SURF":
        feature_extractor = cv2.xfeatures2d.SURF_create()
    elif method == "ORB":
        feature_extractor = cv2.ORB_create()
    else:
        raise ValueError("Invalid feature extraction method.")

    keypoints, descriptors = feature_extractor.detectAndCompute(image, None)
    return keypoints, descriptors

def feature_matching(des1, des2, method, ratio=0.75):
    if method == "SIFT" or method == "SURF":
        matcher = cv2.BFMatcher(cv2.NORM_L2, crossCheck=False)
    elif method == "ORB":
        matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
    else:
        raise ValueError("Invalid feature extraction method.")

    matches = matcher.knnMatch(des1, des2, k=2)
    good_matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * ratio]

    return good_matches

def find_homography_ransac(src_pts, dst_pts, threshold=5, iterations=1000):
    best_homography = None
    max_inliers_count = 0
    n = 4 # Number of points needed to estimate homography
    n_points = len(src_pts)

    for i in range(iterations):
        # Randomly select n points for estimating homography
        indices = np.random.choice(n_points, size=n, replace=False)
        src_pts_subset = src_pts[indices]
        dst_pts_subset = dst_pts[indices]

    # Calculate homography from the selected points
    A = []
    for j in range(n):
        x, y = src_pts_subset[j][0], src_pts_subset[j][1]
        u, v = dst_pts_subset[j][0], dst_pts_subset[j][1]
        A.append([x, y, 1, 0, 0, 0, -u*x, -u*y, -u])
        A.append([0, 0, 0, x, y, 1, -v*x, -v*y, -v])
    A = np.asarray(A)
    U, S, Vh = np.linalg.svd(A)
    L = Vh[-1,:] / Vh[-1,-1]
    H = L.reshape(3, 3)

    # Calculate reprojection errors for all points
    src_pts_hom = np.hstack([src_pts, np.ones((n_points, 1))])
    dst_pts_hom = np.hstack([dst_pts, np.ones((n_points, 1))])
    proj_src_pts = np.matmul(H, src_pts_hom.T)
    proj_src_pts = proj_src_pts / proj_src_pts[-1,:]
    errors = np.sqrt(np.sum((proj_src_pts.T - dst_pts_hom)**2, axis=1))

    # Count inliers and update best_homography if necessary
    inliers_count = np.sum(errors < threshold)
    if inliers_count > max_inliers_count:
        max_inliers_count = inliers_count
        mask = errors < threshold
        src_pts_inliers = src_pts[mask]
        dst_pts_inliers = dst_pts[mask]

    A = []
    for j in range(max_inliers_count):
        x, y = src_pts_inliers[j][0], src_pts_inliers[j][1]
        u, v = dst_pts_inliers[j][0], dst_pts_inliers[j][1]
        A.append([x, y, 1, 0, 0, 0, -u*x, -u*y, -u])
        A.append([0, 0, 0, x, y, 1, -v*x, -v*y, -v])
    A = np.asarray(A)
    U, S, Vh = np.linalg.svd(A)
    L = Vh[-1, :] / Vh[-1, -1]
    best_homography = L.reshape(3, 3)

    return best_homography

def merge_images(img1, img2, H):
    # Determine size of panorama
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]
    if H[2, 2] != 0:
        scale_factor = 1 / H[2, 2]
    else:
        scale_factor = 1
    max_w = int(scale_factor * (w1 + w2))
    max_h = int(scale_factor * (h1 + h2))

    # Warp img2 to img1 coordinate system
    warped_img2 = np.zeros((max_h, max_w, 3), dtype=np.uint8)
    
    for j in range(max_w):
        for i in range(max_h):
            p = np.array([j/scale_factor, i/scale_factor, 1])
            q = np.dot(H, p)
            x, y = int(q[0]/q[2]), int(q[1]/q[2])
            if x >= 0 and x < w2 and y >= 0 and y < h2:
                warped_img2[i, j, :] = img2[y, x, :]

    # Blend the two images
    blended_img = np.zeros((max_h, max_w, 3), dtype=np.uint8)
    blended_img[:h1, :w1, :] = img1

    for i in range(h2):
        for j in range(w2):
            x = int(scale_factor * j + 0.5 * scale_factor)
            y = int(scale_factor * i + 0.5 * scale_factor)
            if warped_img2[y, x, :].all() != 0:
                blended_img[y, x, :] = warped_img2[y, x, :]

    return blended_img

if __name__ == "__main__":
    dataset_path = "path_to_your_dataset"
    image_paths = sorted(glob(os.path.join(dataset_path, "*.png")))

    images = [cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) for image_path in image_paths]

    methods = ["SIFT", "SURF", "ORB"]

    for method in methods:
        start_time = time.time()
        
        # Feature extraction, matching, finding homography, and image merging steps here
        
        runtime = time.time() - start_time
        print(f"{method} runtime: {runtime}s")
        
        # Display your results (plot keypoints, matching lines, panorama, etc.)