import numpy as np
import cv2
import os
from time import sleep
from PIL import Image
import torch

# Install necessary libraries
# Make sure to install YOLOv5 dependencies
# pip install opencv-python pillow torch

class WindowCapture:
    def __init__(self, window_name):
        self.window_name = window_name
        self.capture = cv2.VideoCapture(0)

    def get_screenshot(self):
        ret, frame = self.capture.read()
        if not ret:
            raise Exception('Failed to capture frame from camera.')

        return frame

    def generate_image_dataset(self):
        if not os.path.exists("images"):
            os.mkdir("images")

        while True:
            img = self.get_screenshot()
            im = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            im.save(f"./images/img_{len(os.listdir('images'))}.jpeg")
            sleep(1)

    def get_window_size(self):
        w = int(self.capture.get(3))
        h = int(self.capture.get(4))
        return w, h

class ImageProcessor:
    def __init__(self, img_size, weights_file_path):
        self.model = self.load_yolov5(weights_file_path)
        self.model.to('cuda' if torch.cuda.is_available() else 'cpu')
        self.model.eval()

        self.W, self.H = img_size

    def load_yolov5(self, weights_file_path):
        model = torch.hub.load('ultralytics/yolov5:v5.0', 'yolov5s', pretrained=False)
        checkpoint = torch.load(weights_file_path, map_location='cuda' if torch.cuda.is_available() else 'cpu')
        model.load_state_dict(checkpoint['model'])
        return model

    def process_image(self, img):
        results = self.model(img)
        pred = results.xyxy[0].cpu().numpy()

        # Convert coordinates to match the original image size
        pred[:, [0, 2]] *= self.W
        pred[:, [1, 3]] *= self.H

        return pred

    def draw_identified_objects(self, img, coordinates):
        for coordinate in coordinates:
            x, y, w, h, conf, cls = coordinate

            color = (0, 255, 0)  # Green color for bounding box
            cv2.rectangle(img, (int(x), int(y)), (int(w), int(h)), color, 2)
            cv2.putText(img, f'Class: {int(cls)}, Conf: {conf:.2f}', (int(x), int(y) - 10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
        cv2.imshow('window', img)

# Set your game window name
window_name = "Superfighters Deluxe v1.3.7d"

# Provide the full path to your custom weights file
weights_file_path = r"C:\Users\Ninja.000\Downloads\exp3-20240102T094124Z-001\exp3\weights\best.pt"

wincap = WindowCapture(window_name)
improc = ImageProcessor(wincap.get_window_size(), weights_file_path)

while True:
    ss = wincap.get_screenshot()

    if cv2.waitKey(1) == ord('q'):
        cv2.destroyAllWindows()
        break

    # Preprocess image for YOLOv5
    img = wincap.get_screenshot()
    img = cv2.resize(img, (640, 480))
    img = img.transpose(2, 0, 1)  # Channels first (C, H, W)
    img = np.expand_dims(img, 0)  # Add batch dimension

    # Convert to torch tensor
    img = torch.from_numpy(img).float().div(255.0).unsqueeze(0)

    # Inference and post-process
    coordinates = improc.process_image(img)

    # Draw bounding boxes on the image
    improc.draw_identified_objects(ss, coordinates)

    for coordinate in coordinates:
        print(coordinate)
    print()

    sleep(0.2)

print('Finished.')


C:\Users\Ninja.000\Downloads\Things>python aa.py
Using cache found in C:\Users\Ninja.000/.cache\torch\hub\ultralytics_yolov5_v5.0
Traceback (most recent call last):
  File "C:\Users\Ninja.000\Downloads\Things\aa.py", line 80, in <module>
    improc = ImageProcessor(wincap.get_window_size(), weights_file_path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ninja.000\Downloads\Things\aa.py", line 41, in __init__
    self.model = self.load_yolov5(weights_file_path)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ninja.000\Downloads\Things\aa.py", line 48, in load_yolov5
    model = torch.hub.load('ultralytics/yolov5:v5.0', 'yolov5s', pretrained=False)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ninja.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\torch\hub.py", line 566, in load
    model = _load_local(repo_or_dir, model, *args, **kwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ninja.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\torch\hub.py", line 592, in _load_local
    hub_module = _import_module(MODULE_HUBCONF, hubconf_path)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ninja.000\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\torch\hub.py", line 106, in _import_module
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 936, in exec_module
  File "<frozen importlib._bootstrap_external>", line 1073, in get_code
  File "<frozen importlib._bootstrap_external>", line 1130, in get_data
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Ninja.000/.cache\\torch\\hub\\ultralytics_yolov5_v5.0\\hubconf.py'