Skip to content

Commit b267a9b

Browse files
committed
setinterval to match azure basic performance, modified read me
1 parent 3f66b88 commit b267a9b

File tree

2 files changed

+220
-2
lines changed

2 files changed

+220
-2
lines changed

README.md

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,219 @@
1-
# emotiontracker
1+
````markdown
2+
# Real-Time Emotion and Face Detection App
3+
4+
[![Build and deploy container app to Azure Web App - andre-emotion-app](https://github.com/apaezcastro/emotiontracker/actions/workflows/main_andre-emotion-app.yml/badge.svg)](https://github.com/apaezcastro/emotiontracker/actions/workflows/main_andre-emotion-app.yml)
5+
6+
A full-stack web application that performs real-time emotion detection and face tracking from a live webcam feed. This app uses a Python backend for AI inference and a JavaScript frontend to render the results dynamically on an HTML5 canvas.
7+
8+
**Live Demo:** [andre-emotion-app.azurewebsites.net](https://andre-emotion-app.azurewebsites.net)
9+
10+
---
11+
12+
## Features
13+
14+
* **Live Emotion Detection:** Identifies the user's emotion (e.g., Happy, Sad, Neutral) in real-time.
15+
* **Dynamic Bounding Box:** Draws a precise box around the detected face on the video feed.
16+
* **Responsive UI:** The emotion label is anchored to the bounding box and moves with it.
17+
* **Robust Concurrency:** The app is built with a client-side "lock" to ensure stable, real-time performance by processing one frame at a time, preventing request stacking.
18+
19+
---
20+
21+
## Tech Stack
22+
23+
### Backend
24+
* **Python:** Core application language.
25+
* **Flask:** Serves the API endpoint.
26+
* **Gunicorn:** Production web server (used in Docker).
27+
* **OpenCV (`opencv-python-headless`):** For image processing (`imdecode`) and face detection (Haar Cascades).
28+
* **ONNXRuntime:** To run the `emotion-ferplus-8.onnx` model.
29+
* **NumPy:** For high-performance array manipulation.
30+
* **Flask-Cors:** To handle cross-origin requests from the frontend.
31+
32+
### Frontend
33+
* **HTML5:** `video` and `canvas` elements for video streaming.
34+
* **CSS3:** Styling for the video, bounding box, and overlay.
35+
* **JavaScript (ES6+):** Manages the `setInterval` loop, captures frames, and uses the `fetch` API.
36+
37+
### Deployment
38+
* **Docker:** Containerizes the Python backend for consistent, isolated deployment.
39+
* **GitHub:** Source code repository.
40+
* **Azure (CI/CD):** Automated build and deployment pipeline (via GitHub Actions) to an Azure App Service.
41+
42+
---
43+
44+
## 🚀 Getting Started (Running Locally)
45+
46+
There are two ways to run this project locally. Docker is the recommended method as it handles all dependencies automatically.
47+
48+
### Prerequisites
49+
50+
* [Git](https://git-scm.com/downloads)
51+
* [Node.js (which includes npm)](https://nodejs.org/)
52+
* [Docker Desktop](https://www.docker.com/products/docker-desktop/) (for the Docker method)
53+
* [Python 3.8+](https://www.python.org/downloads/) (for the manual Python method)
54+
55+
---
56+
57+
### Option 1: Running with Docker (Recommended)
58+
59+
This method builds the backend in a container, so you do not need to install Python or any packages on your local machine.
60+
61+
**1. Clone the Repository**
62+
```sh
63+
git clone [https://github.com/apaezcastro/emotiontracker.git](https://github.com/apaezcastro/emotiontracker.git)
64+
cd emotiontracker
65+
````
66+
67+
**2. Download Model Files**
68+
69+
The Docker build expects the model files to be present.
70+
71+
* **Emotion Model (`emotion-ferplus-8.onnx`):**
72+
Download it from the ONNX Model Zoo [here](https://www.google.com/search?q=https://github.com/onnx/models/raw/main/vision/body_analysis/emotion_ferplus/model/emotion-ferplus-8.onnx).
73+
Place this file in the `backend/` directory.
74+
75+
* **Face Detection Model (`haarcascade_frontalface_default.xml`):**
76+
Download it from the OpenCV repository [here](https://www.google.com/search?q=https://github.com/opencv/opencv/raw/master/data/haarcascades/haarcascade_frontalface_default.xml).
77+
Place this file in the `backend/` directory.
78+
79+
**3. Build and Run the Backend Container**
80+
81+
```sh
82+
# Navigate to the backend directory
83+
cd backend
84+
85+
# Build the Docker image
86+
docker build -t emotion-app-backend .
87+
88+
# Run the container, mapping port 5000
89+
docker run -p 5000:5000 emotion-app-backend
90+
```
91+
92+
The backend is now running on `http://localhost:5000`.
93+
94+
**4. Run the Frontend**
95+
96+
In a **new terminal**, navigate to the frontend directory:
97+
98+
```sh
99+
# (From the root directory)
100+
cd frontend
101+
102+
# Install npm packages
103+
npm install
104+
105+
# Run the development server
106+
npm start
107+
```
108+
109+
Your browser will open to `http://localhost:3000`, which will connect to the backend container running on port 5000.
110+
111+
-----
112+
113+
### Option 2: Running Manually (Python & Node.js)
114+
115+
This method requires you to set up both the Python and Node.js environments manually.
116+
117+
**1. Clone the Repository**
118+
119+
```sh
120+
git clone [https://github.com/apaezcastro/emotiontracker.git](https://github.com/apaezcastro/emotiontracker.git)
121+
cd emotiontracker
122+
```
123+
124+
**2. Download Model Files**
125+
126+
* **Emotion Model (`emotion-ferplus-8.onnx`):**
127+
Download it from the ONNX Model Zoo [here](https://www.google.com/search?q=https://github.com/onnx/models/raw/main/vision/body_analysis/emotion_ferplus/model/emotion-ferplus-8.onnx).
128+
Place this file in the `backend/` directory.
129+
130+
* **Face Detection Model (`haarcascade_frontalface_default.xml`):**
131+
Download it from the OpenCV repository [here](https://www.google.com/search?q=https://github.com/opencv/opencv/raw/master/data/haarcascades/haarcascade_frontalface_default.xml).
132+
Place this file in the `backend/` directory.
133+
134+
**3. Backend Setup (Python)**
135+
136+
```sh
137+
# Navigate to the backend directory
138+
cd backend
139+
140+
# Create a virtual environment
141+
python -m venv venv
142+
source venv/bin/activate # On Windows, use `venv\Scripts\activate`
143+
144+
# Install required packages
145+
pip install -r requirements.txt
146+
147+
# Run the Flask server
148+
# (It will typically run on http://localhost:5000)
149+
python app.py
150+
```
151+
152+
**4. Frontend Setup (JavaScript)**
153+
154+
In a **new terminal**:
155+
156+
```sh
157+
# Navigate to the frontend directory
158+
cd frontend
159+
160+
# Install npm packages
161+
npm install
162+
163+
# Run the development server
164+
npm start
165+
```
166+
167+
**5. View Your App**
168+
169+
Open your browser and go to `http://localhost:3000`.
170+
171+
-----
172+
173+
## How It Works
174+
175+
1. The JavaScript frontend uses `setInterval` (set to `1000ms` for production) to capture a frame from the user's webcam.
176+
2. The frame is drawn to an HTML `canvas` and exported as a `image/jpeg` base64 data URL.
177+
3. This data is sent via a `fetch` POST request to the `/detect_emotion` API endpoint.
178+
4. A **concurrency lock** (`analyzing` flag) in JavaScript ensures that if the server *does* take longer than the interval, a new request is not sent until the previous one completes.
179+
5. The Python backend receives the JSON, decodes the base64 string into a NumPy array (`nparr`), and then uses `cv2.imdecode` to create an image.
180+
6. The AI model runs, returning the emotion and a 1D array for the face coordinates: `[x, y, width, height]`.
181+
7. The Python backend converts the NumPy array to a standard Python list (`.tolist()`) and returns the emotion and coordinates as JSON.
182+
8. The frontend receives the JSON, clears any old bounding boxes, and draws a new box and emotion overlay using the received coordinates.
183+
184+
-----
185+
186+
## Design Choices & Key Learnings
187+
188+
This project involved several key design decisions to achieve a stable, real-time feel.
189+
190+
* **Concurrency Lock (`analyzing` flag):** This is the most critical design choice. It prevents "request stacking" and makes the app resilient to performance differences between servers.
191+
192+
* **Locally:** On a 12-core machine, the detection runs in `~100ms`, allowing for a 10 FPS loop.
193+
* **On Azure (Shared Tier):** The same detection takes `~700-900ms`. The `analyzing` flag gracefully handles this, ensuring the app remains stable and simply updates less frequently, rather than crashing.
194+
195+
* **Lightweight Data Transfer:** The backend only sends back tiny JSON packets (e.g., `~400B`) containing the emotion string and four coordinates. This ensures that the bottleneck is *always* CPU processing time, not network lag.
196+
197+
* **NumPy to List (`.tolist()`):** A `numpy.ndarray` is not JSON serializable. The `.tolist()` method was essential to convert the detection results into a standard Python list that Flask/FastAPI can serialize into JSON.
198+
199+
* **Single Face (1D Array):** The app is currently optimized to detect the single most prominent face, returning a simple 1D array `[x, y, w, h]`. This simplified the frontend logic, though it's a target for future improvement.
200+
201+
* **Frontend Error Handling:** The frontend JavaScript checks if `faceData` exists before trying to draw a box. This prevents a `TypeError` and allows the app to run smoothly, simply hiding the box when no face is detected.
202+
203+
-----
204+
205+
## Future Improvements
206+
207+
* **Upgrade to a Modern Face Detector:** The current implementation uses OpenCV's classic Haar Cascades. A significant improvement would be to replace this with **YuNet**, a lightweight and highly accurate deep-learning detector from the OpenCV model zoo. This would dramatically improve detection accuracy with varied angles, lighting, and partial occlusions.
208+
* **Support Multiple Faces:** The backend could be refactored to *always* send a 2D array (a list of faces), e.g., `[[x,y,w,h], [x2,y2,w2,h2]]`. The frontend would then use a `forEach` loop to draw a box for every face detected.
209+
210+
-----
211+
212+
## Acknowledgements & Credits
213+
214+
* **AI Model:** This project uses the `emotion-ferplus-8.onnx` model from the [ONNX Model Zoo](https://github.com/onnx/models/tree/main/vision/body_analysis/emotion_ferplus), which is trained on the FER+ dataset.
215+
* **Libraries:** This project would not be possible without the open-source work from OpenCV, Flask, ONNXRuntime, and NumPy.
216+
217+
218+
```
219+
```

static/script.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,4 @@ setInterval(() => {
7373
overlay.textContent = 'Error';
7474
console.error('Detection error:', err);
7575
});
76-
}, 100);
76+
}, 1000);

0 commit comments

Comments
 (0)