Bridge between local PC and cloud GPU processing
Project description
Overlink - Cloud GPU Bridge
Overlink is a Python framework that connects your local application to cloud GPU resources (Google Colab, Kaggle, etc.) through ngrok tunnels. With Overlink, you can easily leverage powerful cloud GPUs without complicated setup.
🌟 Key Features
- 🚀 Automatic ngrok tunnel setup - No manual configuration needed
- ⚡ Leverage cloud GPUs - Handle intensive AI/ML tasks seamlessly
- 🔄 Simple API - Easy integration into existing projects
- 🔒 Secure HTTPS connection - Safeguard your data
- 📊 Connection monitoring - Track server status in real time
- 🧩 YOLO model support - Built-in Ultralytics YOLOv5/v8 integration
📦 Installation
Install Overlink via pip:
pip install overlink
System requirements:
- Python 3.6+
- Dependencies are automatically installed with the package
🚀 Quick Start
1. Setup server on Google Colab
!pip install -q overlink
from overlink import OvercloudServer
import getpass
# Enter your ngrok authtoken (get it at: https://dashboard.ngrok.com/get-started/your-authtoken)
ngrok_token = getpass.getpass("🔑 Enter your ngrok authtoken: ")
# Initialize the server
server = OvercloudServer(
authtoken=ngrok_token,
model_path="/content/yolov8n.pt", # Path to your model
port=5000 # Optional port (default: 3001)
)
# Start the server and get the public URL
public_url = server.start()
# Keep the server running
server.keep_alive()
2. Use client on your local machine
from overlink import OvercloudClient
import cv2
# Initialize the client with the server URL
client = OvercloudClient("https://your-ngrok-url")
# Check connection
if client.ping():
print("✅ Successfully connected to cloud GPU!")
# Process image via cloud
result = client.process_image("input.jpg")
# Display and save the result
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.imwrite("output.jpg", result)
else:
print("❌ Cannot connect to server")
📚 Detailed Guide
Server configuration
| Parameter | Default | Description |
|---|---|---|
authtoken |
Required | Ngrok authtoken (get from ngrok dashboard) |
model_path |
None |
Path to YOLO model (.pt file) |
port |
3001 |
Local port for Flask server |
flask_debug |
False |
Enable Flask debug mode |
Advanced Example:
server = OvercloudServer(
authtoken="2w1Z93Yc23gB6Jl6jncvYfEkQC4_KpA55x6yTnakDb81HXJo",
model_path="/content/custom_model.pt",
port=5000
)
# Custom image processing endpoint
@server.app.route('/custom-process', methods=['POST'])
def custom_process():
# Add your custom processing code here
pass
public_url = server.start()
Using the client
Main methods
ping()- Check server connectivity- Returns
Trueif the server is up,Falseotherwise
- Returns
process_image(image_path)- Process an image via the serverimage_path: Path to the image file to process- Returns the processed image as a numpy array (OpenCV format)
Example: Batch processing
import os
from tqdm import tqdm
input_dir = "input_images"
output_dir = "processed_images"
os.makedirs(output_dir, exist_ok=True)
for filename in tqdm(os.listdir(input_dir)):
if filename.endswith(('.jpg', '.png', '.jpeg')):
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(output_dir, f"processed_{filename}")
try:
result = client.process_image(input_path)
cv2.imwrite(output_path, result)
except Exception as e:
print(f"Error processing {filename}: {str(e)}")
🧪 Performance Test
| Input Image | Processing Time (Colab T4 GPU) | Processing Time (Local CPU) |
|---|---|---|
| 640x480 | 120ms | 850ms |
| 1280x720 | 250ms | 2200ms |
| 1920x1080 | 450ms | 4800ms |
Test results with YOLOv8n using the same hardware
🔧 Common Troubleshooting
-
Ngrok connection error
- Make sure your authtoken is correct
- Check the server's internet connection
-
Timeout while processing image
- Increase timeout on the client:
# In client.py, update timeout=60 response = requests.post(..., timeout=60)
- Reduce the input image size
- Increase timeout on the client:
-
Failed to load model
- Check the model path on the server
- Ensure the model is compatible with the Ultralytics version
-
GPU out of memory
- Reduce batch size
- Use a smaller model
- Upgrade your Colab GPU (Pro/Premium)
🌐 System Architecture
graph LR
A[Local PC] -->|Send image| B[OvercloudClient]
B -->|HTTPS Request| C[ngrok Tunnel]
C --> D[Cloud Server]
D -->|GPU Processing| E[YOLO Model]
E -->|Result| D
D -->|Response| C
C -->|Processed image| B
B --> A
💡 Example Applications
1. GUI Client (using Tkinter)
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import cv2
import numpy as np
from overlink import OvercloudClient
class OverlinkGUI(tk.Tk):
def __init__(self):
super().__init__()
self.title("Overlink Client")
self.geometry("1200x600")
# Build user interface
self.create_widgets()
# Initialize client
self.client = None
def create_widgets(self):
# URL input section
url_frame = tk.Frame(self)
url_frame.pack(fill=tk.X, padx=10, pady=10)
tk.Label(url_frame, text="Server URL:").pack(side=tk.LEFT)
self.url_entry = tk.Entry(url_frame, width=50)
self.url_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
self.connect_btn = tk.Button(
url_frame,
text="Connect",
command=self.connect_server
)
self.connect_btn.pack(side=tk.LEFT)
# Image display sections
img_frame = tk.Frame(self)
img_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Original image
self.orig_frame = tk.LabelFrame(img_frame, text="Original Image")
self.orig_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5)
self.orig_label = tk.Label(self.orig_frame)
self.orig_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# Processed result image
self.result_frame = tk.LabelFrame(img_frame, text="Result")
self.result_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5)
self.result_label = tk.Label(self.result_frame)
self.result_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# Action buttons
btn_frame = tk.Frame(self)
btn_frame.pack(fill=tk.X, pady=10)
self.select_btn = tk.Button(
btn_frame,
text="Choose Image",
command=self.select_image,
state=tk.DISABLED
)
self.select_btn.pack(side=tk.LEFT, padx=20)
self.save_btn = tk.Button(
btn_frame,
text="Save Result",
command=self.save_result,
state=tk.DISABLED
)
self.save_btn.pack(side=tk.LEFT, padx=20)
# Status bar
self.status_var = tk.StringVar(value="Not connected")
status_bar = tk.Label(self, textvariable=self.status_var, bd=1, relief=tk.SUNKEN, anchor=tk.W)
status_bar.pack(side=tk.BOTTOM, fill=tk.X)
def connect_server(self):
server_url = self.url_entry.get().strip()
if not server_url:
self.status_var.set("❌ Please enter the server URL")
return
try:
self.client = OvercloudClient(server_url)
if self.client.ping():
self.status_var.set(f"✅ Connected to: {server_url}")
self.select_btn.config(state=tk.NORMAL)
else:
self.status_var.set(f"❌ Cannot connect to server")
except Exception as e:
self.status_var.set(f"Connection error: {str(e)}")
def select_image(self):
file_path = filedialog.askopenfilename(
filetypes=[("Image files", "*.jpg *.jpeg *.png")]
)
if file_path:
# Display original image
self.display_image(file_path, self.orig_label)
# Process the image
self.process_image(file_path)
def process_image(self, file_path):
try:
result = self.client.process_image(file_path)
# Convert for display
result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)
self.result_image = Image.fromarray(result_rgb)
self.display_result(self.result_image)
self.status_var.set("✅ Successfully processed!")
self.save_btn.config(state=tk.NORMAL)
except Exception as e:
self.status_var.set(f"❌ Processing error: {str(e)}")
def display_image(self, path, label):
img = Image.open(path)
img.thumbnail((500, 500))
photo = ImageTk.PhotoImage(img)
label.config(image=photo)
label.image = photo
def display_result(self, img):
img.thumbnail((500, 500))
photo = ImageTk.PhotoImage(img)
self.result_label.config(image=photo)
self.result_label.image = photo
def save_result(self):
if hasattr(self, 'result_image'):
file_path = filedialog.asksaveasfilename(
defaultextension=".jpg",
filetypes=[("JPEG files", "*.jpg"), ("All files", "*.*")]
)
if file_path:
self.result_image.save(file_path)
self.status_var.set(f"✅ Saved at: {file_path}")
if __name__ == "__main__":
app = OverlinkGUI()
app.mainloop()
2. Integrate into image processing pipeline
from overlink import OvercloudClient
import cv2
import time
class ImageProcessor:
def __init__(self, use_cloud=False, cloud_url=None):
self.use_cloud = use_cloud
if use_cloud:
self.client = OvercloudClient(cloud_url)
assert self.client.ping(), "Cannot connect to cloud server"
def process(self, image):
if self.use_cloud:
# Save a temp image to send to server
temp_path = "temp_input.jpg"
cv2.imwrite(temp_path, image)
return self.client.process_image(temp_path)
else:
# Local processing
return self.local_processing(image)
def local_processing(self, image):
# Your CPU local processing code here
# ...
return processed_image
# Usage
processor = ImageProcessor(
use_cloud=True,
cloud_url="https://your-ngrok-url"
)
cap = cv2.VideoCapture(0) # Webcam
while True:
ret, frame = cap.read()
if not ret:
break
start = time.time()
result = processor.process(frame)
fps = 1 / (time.time() - start)
cv2.putText(result, f"FPS: {fps:.1f}", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("Real-time Processing", result)
if cv2.waitKey(1) == 27: # ESC
break
cap.release()
cv2.destroyAllWindows()
🤝 Contributions
Overlink is an open source project and welcomes all contributions! Get involved by:
- Reporting bugs: Open an issue on GitHub
- Suggesting features: Share your new ideas
- Contributing code: Submit a pull request
- Improving documentation: Help make the docs clearer
Detailed contribution guide:
# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/username/overlink.git
# 3. Create a new branch
git checkout -b feature/new-feature
# 4. Make changes
# 5. Commit and push
git push origin feature/new-feature
# 6. Open a pull request
📜 License
This project is distributed under the MIT License. See the LICENSE file for more details.
📞 Contact
- Author: KhanhRomVN
- Email: khanhromvn@gmail.com
- GitHub: https://github.com/KhanhRomVN
- Project: https://github.com/KhanhRomVN/overlink
🙏 Credits
Overlink relies on these awesome open source projects:
- Ultralytics YOLO - Object detection framework
- Flask - Web framework
- Pyngrok - Python wrapper for ngrok
- OpenCV - Image processing
Overlink – The simple bridge between your local application and the power of cloud GPUs!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file overlink-0.4.0.tar.gz.
File metadata
- Download URL: overlink-0.4.0.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea37fce903411f202e5007d346c51f63eaf69dceaeba187f9bac0fd2de62b1aa
|
|
| MD5 |
0e06cfd77fa23a93a628e79fc160c069
|
|
| BLAKE2b-256 |
e903516c4334c5cb72297bc28e39eede55d677a0aa2b593673bc145e642af4e5
|
File details
Details for the file overlink-0.4.0-py3-none-any.whl.
File metadata
- Download URL: overlink-0.4.0-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46d66dfb2db2bbff69de7b0d5a076e93cd3b26fade813d656386cb7caf39c8ee
|
|
| MD5 |
8a028f685d77713166ae9fc0175033d4
|
|
| BLAKE2b-256 |
cab3b84d64df0c5469e12279eb9ea998a3cbe360194642ff71aa673da13b1e30
|