i will give you my point cloud generation code. you will implement the output of given script to your written code. also generate functions like detect_loop_closure that you written you can write them. give me whole code to create slam from video. here is the point cloud generation script. you will call this script to the main script. you can differ the given point cloud generation script because for now it is saving point clouds as txt. so you must change the script in way that it can be called from main slam script.

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

import cv2
import torch
import numpy as np
import os
from open3d import *
from datetime import datetime

# Q matrix - Camera parameters - Can also be found using stereoRectify
Q = np.array(([1.0, 0.0, 0.0, -160.0],
              [0.0, 1.0, 0.0, -120.0],
              [0.0, 0.0, 0.0, 350.0],
              [0.0, 0.0, 1.0/90.0, 0.0]), dtype=np.float32)

# Load a MiDaS model for depth estimation
model_type = "MiDaS_small"  # MiDaS v2.1 - Small (lowest accuracy, highest inference speed)
midas = torch.hub.load("intel-isl/MiDaS", model_type)
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
midas.to(device)
midas.eval()
midas_transforms = torch.hub.load("intel-isl/MiDaS", "transforms")
if model_type == "DPT_Large" or model_type == "DPT_Hybrid":
    transform = midas_transforms.dpt_transform
else:
    transform = midas_transforms.small_transform

# Open video file
video_path = 'video.mp4'  # Replace 'your_video.mp4' with the path to your video file
cap = cv2.VideoCapture(video_path)

# Define frame counter and interval for depth estimation
frame_counter = 0
save_interval = 5  # Save every 5th frame

# Create directories for saving images and point clouds
rgb_dir = "rgb_images"
depth_dir = "depth_maps"
txt_dir = "point_clouds_txt"
os.makedirs(rgb_dir, exist_ok=True)
os.makedirs(depth_dir, exist_ok=True)
os.makedirs(txt_dir, exist_ok=True)

def save_point_cloud_txt(filename, points, colors):
    """Saves point cloud data as a .txt file."""
    with open(filename, 'w') as f:
        for p, c in zip(points, colors):
            f.write(f"{p[0]} {p[1]} {p[2]} {int(c[0])} {int(c[1])} {int(c[2])}\n")

while True:
    dt0 = datetime.now()

    # Read frame from video
    ret, color_image = cap.read()

    if not ret:
        break

    # Increment frame counter
    frame_counter += 1

    # Convert color image to RGB format
    img = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB)
    R = np.array([
        [0, 0, -1],
        [0, 1, 0],
        [1, 0, 0]
    ])
    # Apply input transforms for MiDaS model and perform depth estimation
    if frame_counter % save_interval == 0:
        input_batch = transform(img).to(device)

        with torch.no_grad():
            prediction = midas(input_batch)
            prediction = torch.nn.functional.interpolate(
                prediction.unsqueeze(1),
                size=img.shape[:2],
                mode="bicubic",
                align_corners=False,
            ).squeeze()

        depth_map = prediction.cpu().numpy()

        # Reproject points into 3D
        points_3D = cv2.reprojectImageTo3D(depth_map, Q, handleMissingValues=False)

        # Mask out points with invalid depth
        mask_map = depth_map > 0.4

        # Keep only valid points and colors
        output_points = points_3D[mask_map]
        output_colors = img[mask_map]

        # Downsample point cloud (Correctly)
        voxel_size = 0.00005  # Adjust as needed
        pcd = geometry.PointCloud()
        pcd.points = utility.Vector3dVector(output_points[::int(voxel_size * output_points.shape[0])])  # Correct indexing
        pcd.colors = utility.Vector3dVector(output_colors[::int(voxel_size * output_colors.shape[0])] / 255.0)
        pcd.rotate(R, center=np.array([0, 0, 0]).reshape(3, 1))  # Rotate around the origin
        # Transform point cloud
        pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])

        # Prepare data for saving as .txt
        points = np.asarray(pcd.points)
        colors = np.asarray(pcd.colors) * 255  # Scale colors back to [0, 255]

        # Save the point cloud as a .txt file
        txt_filename = os.path.join(txt_dir, f"pointcloud{frame_counter:05d}.txt")
        save_point_cloud_txt(txt_filename, points, colors)

    process_time = datetime.now() - dt0
    print("FPS: " + str(1 / process_time.total_seconds()))

    # Check for user input to exit the loop
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()