Skip to content

Commit fa17aa3

Browse files
first commit
0 parents  commit fa17aa3

19 files changed

Lines changed: 864 additions & 0 deletions

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.pyo
5+
*.pyd
6+
*.so
7+
*.egg-info/
8+
.eggs/
9+
build/
10+
dist/
11+
12+
# Virtual environments
13+
.venv/
14+
venv/
15+
env/
16+
17+
# IDE / editor
18+
.vscode/
19+
.idea/
20+
*.suo
21+
*.user
22+
*.userosscache
23+
*.sln.docstates
24+
25+
# OS files
26+
.DS_Store
27+
Thumbs.db
28+
29+
# Logs
30+
*.log
31+
logs/
32+
33+
# Runtime / local files
34+
output/
35+
*.tmp
36+
*.bak
37+
38+
# Temp folder
39+
temp/

README.md

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# Multi-Camera Simulation Engine
2+
3+
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
4+
[![OpenGL 3.3+](https://img.shields.io/badge/OpenGL-3.3+-orange.svg)](https://www.opengl.org/)
5+
[![Flask 2.0+](https://img.shields.io/badge/flask-2.0+-green.svg)](https://flask.palletsprojects.com/)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7+
8+
A high-performance, Python-based offscreen 3D camera simulation engine. It renders a virtual scene with a rotating camera using OpenGL and publishes the result as a real-time MJPEG IP camera stream, designed specifically for imaging system simulation experiments and computer vision testing.
9+
10+
![Simulation Demo](doc/image1_1.png)
11+
12+
---
13+
14+
## 📌 Overview
15+
16+
The **Multi-Camera Simulation Engine** provides a lightweight virtual environment for researchers and developers to simulate complex imaging systems. By leveraging thread-safe offscreen rendering and MJPEG streaming, it provides a "virtual" IP camera feed that can be consumed by standard video clients or computer vision pipelines without requiring a physical camera or a visible UI.
17+
18+
### 🌟 Project Vision & Background
19+
This project was conceived to demonstrate the feasibility of high-fidelity imaging system simulation tools, particularly for consumer hardware products. It aligns with advanced industry workflows involving:
20+
- **System Design & Validation**: Defining simulation capabilities and performance goals to validate against real hardware.
21+
- **Multi-Camera R&D**: Investigating imaging performance goals and spatial configurations for multi-camera systems (including XR applications).
22+
- **Cross-Functional Collaboration**: Bridging the gap between Product Design (PD), Electrical Engineering (EE), Camera Hardware, and Software teams through early-stage virtual prototyping.
23+
24+
This repository represents the **beginning of a medium-to-large scale open-source project** aimed at providing accessible, professional-grade simulation tools for the computer vision and hardware engineering communities.
25+
26+
### Key Applications
27+
- **Computer Vision Development**: Validate tracking and detection algorithms against ground-truth controlled virtual environments.
28+
- **Imaging System R&D**: Simulate varying camera parameters (FOV, resolution, placement) before physical deployment.
29+
- **Robotics & XR Simulation**: Provide low-latency visual feedback for autonomous agent training and augmented reality testing.
30+
31+
## 🚀 Key Features
32+
33+
- **Real-time 3D Rendering**: High-performance rendering via OpenGL 3.3+ with Phong shading (ambient, diffuse, specular) and directional lighting.
34+
- **Thread-Safe Offscreen Pipeline**: Uses hidden GLFW windows and custom Framebuffer Objects (FBOs) for background rendering, optimized for multi-threaded Flask environments.
35+
- **MJPEG IP Camera Stream**: Efficiently broadcasts rendered frames over HTTP, mimicking a real network-attached camera.
36+
- **Dynamic Orbit Camera**: Configurable virtual camera with adjustable FOV, near/far planes, and procedural orbit logic.
37+
- **Procedural Scene Elements**: Includes a built-in ground plane with checkerboard textures for spatial reference and a central cube.
38+
- **Modular Architecture**: Clean separation between core logic, rendering, streaming, and web interfaces for easy extensibility.
39+
40+
## 📁 Project Structure
41+
42+
```text
43+
Multi-Camera-Simulation-Engine/
44+
├── config/ # Application and camera configuration (settings.json)
45+
├── core/ # Orchestration and state management
46+
│ ├── app.py # Main application orchestrator (MiniCamSimApp)
47+
│ └── state.py # Settings loader and global state management
48+
├── doc/ # Documentation assets and diagrams
49+
├── effects/ # Post-processing and image effect hooks
50+
├── render/ # OpenGL rendering engine
51+
│ ├── camera.py # Camera view and projection logic
52+
│ └── renderer.py # OpenGL context, shaders, and geometry management
53+
├── stream/ # Video broadcasting components
54+
│ └── mjpeg_stream.py # MJPEG encoding and HTTP streaming logic
55+
├── utils/ # General utility helpers
56+
├── web/ # Flask web interface
57+
│ ├── routes.py # API and stream endpoints
58+
│ ├── static/ # CSS/JS assets
59+
│ └── templates/ # Dashboard UI (index.html)
60+
├── main.py # Application entry point
61+
└── requirements.txt # Project dependencies
62+
```
63+
64+
## 🛠️ Installation & Setup
65+
66+
### Prerequisites
67+
- **Python 3.8+**
68+
- **OpenGL 3.3+** compatible graphics hardware
69+
- **GLFW** library (usually handled via `glfw` python package, but requires system-level OpenGL drivers)
70+
71+
### 1. Clone the Repository
72+
```bash
73+
git clone https://github.com/your-username/Multi-Camera-Simulation-Engine.git
74+
cd Multi-Camera-Simulation-Engine
75+
```
76+
77+
### 2. Prepare Environment
78+
```bash
79+
# Create and activate virtual environment
80+
python -m venv venv
81+
source venv/bin/activate # Linux/macOS
82+
# or
83+
venv\Scripts\activate # Windows
84+
```
85+
86+
### 3. Install Dependencies
87+
```bash
88+
pip install -r requirements.txt
89+
```
90+
91+
## 🚀 Quick Start
92+
93+
Launch the engine with a single command:
94+
95+
```bash
96+
python main.py
97+
```
98+
99+
Once running, the engine starts a local Flask server:
100+
- **Web Dashboard**: [http://localhost:5000](http://localhost:5000)
101+
- **Direct MJPEG Stream**: [http://localhost:5000/cam](http://localhost:5000/cam)
102+
103+
### Live Stream Preview
104+
When you access the direct stream or the web dashboard, you will see the real-time offscreen rendered view:
105+
106+
![Live MJPEG Stream Screenshot](doc/image1_2.png)
107+
*(Note: Example of the real-time rotating camera feed served via MJPEG over HTTP)*
108+
109+
## ⚙️ Configuration
110+
111+
The engine is highly customizable via `config/settings.json`. The file is automatically generated with defaults on the first run.
112+
113+
### Default Configuration Schema
114+
```json
115+
{
116+
"app": {
117+
"host": "127.0.0.1",
118+
"port": 5000,
119+
"fps": 30,
120+
"width": 1280,
121+
"height": 720
122+
},
123+
"camera": {
124+
"radius": 8.0,
125+
"height": 3.5,
126+
"angular_speed_deg": 20.0,
127+
"target": [0.0, 0.5, 0.0],
128+
"fov_deg": 45.0,
129+
"near": 0.1,
130+
"far": 100.0
131+
},
132+
"light": {
133+
"position": [6.0, 8.0, 6.0]
134+
}
135+
}
136+
```
137+
138+
## 🧠 Technical Architecture
139+
140+
The Multi-Camera Simulation Engine is built around a modular architecture to ensure scalability:
141+
142+
- **`MiniCamSimApp` (`core/app.py`)**: The central orchestrator. It initializes the `AppState`, `Renderer`, and `MjpegStreamer` and registers the web routes.
143+
- **`AppState` (`core/state.py`)**: Manages global application state and loads configuration from `settings.json`.
144+
- **`Renderer` (`render/renderer.py`)**: The heart of the 3D visualization. It handles:
145+
- **GLFW Context Management**: Initializes a hidden GLFW window and manages the OpenGL context, crucial for thread-safe rendering in a multi-threaded Flask environment.
146+
- **Shader Program**: Compiles GLSL vertex and fragment shaders for Phong shading, enabling realistic lighting (ambient, diffuse, specular) and object coloring (including a checkerboard ground plane).
147+
- **Geometry Buffers**: Sets up Vertex Array Objects (VAOs), Vertex Buffer Objects (VBOs), and Element Buffer Objects (EBOs) for rendering 3D objects.
148+
- **Framebuffer Object (FBO)**: Renders directly to an off-screen framebuffer, allowing the rendered image to be read back into a NumPy array without displaying a window.
149+
- **`MjpegStreamer` (`stream/mjpeg_stream.py`)**: Responsible for encoding rendered frames into MJPEG format and serving them over HTTP using OpenCV and Flask Response.
150+
151+
## 🚧 Limitations & Future Work
152+
153+
### Current Limitations
154+
- **Single Camera Stream**: Currently, the engine supports one active camera stream at a time.
155+
- **Basic Scene**: The 3D scene is currently limited to a cube and a ground plane.
156+
- **Passive Interface**: The web dashboard is read-only; no interactive controls for the camera are available yet.
157+
158+
### Future Enhancements
159+
- **Multi-Camera Support**: Simultaneous rendering and streaming of multiple virtual cameras.
160+
- **Model Loading**: Support for loading complex 3D models (OBJ, GLTF).
161+
- **Interactive UI**: Real-time controls for camera movement, FOV, and lighting parameters via the web dashboard.
162+
- **Post-Processing**: Integration of image effects (noise, lens distortion, color correction).
163+
- **Plugin System**: Formal plugin system for adding new rendering effects or camera types.
164+
- **REST API**: Programmatic control of simulation parameters via a dedicated API.
165+
166+
## 🤝 Contributing
167+
168+
Contributions are welcome! Whether it's adding support for multiple cameras, improving the UI, or implementing new post-processing effects.
169+
170+
1. Fork the Project
171+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
172+
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
173+
4. Push to the Branch (`git push origin feature/AmazingFeature`)
174+
5. Open a Pull Request
175+
176+
## 📄 License
177+
178+
Distributed under the MIT License. See `LICENSE` for more information.
179+
180+
# Author
181+
182+
**Sayed Ahmadreza Razian, PhD**
183+
184+
LinkedIn\
185+
https://www.linkedin.com/in/ahmadrezarazian/
186+
187+
Google Scholar\
188+
https://scholar.google.com/citations?user=Dh9Iy2YAAAAJ
189+
190+
Email\
191+
AhmadrezaRazian@gmail.com
192+
193+
Feel free to contact me for collaboration or questions.
194+
195+
---
196+
*Developed for advanced imaging system simulation and computer vision research.*

config/settings.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"app": {
3+
"host": "127.0.0.1",
4+
"port": 5000,
5+
"fps": 30,
6+
"width": 640,
7+
"height": 480
8+
},
9+
"camera": {
10+
"radius": 8.0,
11+
"height": 3.5,
12+
"angular_speed_deg": 20.0,
13+
"target": [0.0, 0.5, 0.0],
14+
"fov_deg": 45.0,
15+
"near": 0.1,
16+
"far": 100.0
17+
},
18+
"light": {
19+
"position": [6.0, 8.0, 6.0]
20+
}
21+
}

core/app.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from flask import Flask
2+
from .state import AppState
3+
from render.renderer import Renderer
4+
from stream.mjpeg_stream import MjpegStreamer
5+
from web.routes import register_routes
6+
7+
8+
class MiniCamSimApp:
9+
def __init__(self):
10+
self.state = AppState()
11+
self.flask_app = Flask(__name__, template_folder='../web/templates', static_folder='../web/static')
12+
13+
settings = self.state.settings
14+
self.renderer = Renderer(settings)
15+
self.streamer = MjpegStreamer(self.renderer, fps=settings['app']['fps'])
16+
17+
register_routes(self.flask_app, self.streamer)
18+
19+
def run(self):
20+
app_cfg = self.state.settings['app']
21+
self.flask_app.run(host=app_cfg['host'], port=app_cfg['port'], threaded=True)

core/state.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from pathlib import Path
2+
import json
3+
4+
class AppState:
5+
def __init__(self):
6+
settings_path = Path(__file__).resolve().parent.parent / "config" / "settings.json"
7+
8+
default_settings = {
9+
"width": 640,
10+
"height": 480,
11+
"fps": 30,
12+
"camera": {
13+
"radius": 5.0,
14+
"speed": 0.5
15+
}
16+
}
17+
18+
if not settings_path.exists():
19+
settings_path.parent.mkdir(parents=True, exist_ok=True)
20+
with open(settings_path, "w", encoding="utf-8") as f:
21+
json.dump(default_settings, f, indent=4)
22+
self.settings = default_settings
23+
else:
24+
with open(settings_path, "r", encoding="utf-8") as f:
25+
self.settings = json.load(f)

debug_frame.png

19.3 KB
Loading

doc/image1_1.png

282 KB
Loading

doc/image1_2.png

260 KB
Loading

effects/image_effects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# V3 placeholder.

frame_denug.jpg

96.5 KB
Loading

0 commit comments

Comments
 (0)