https://github.com/mrazza/cctv-home-occupancy
A CPU-optimized local Linux pipeline using OpenAI CV and YOLOv8/ByteTrack to monitor home occupancy via RTSP streams, featuring directional tripwire tracking and a FastAPI query endpoint.
https://github.com/mrazza/cctv-home-occupancy
bytetrack computer-vision fastapi home-automation motion-detection object-tracking opencv rtsp sqlite yolov8
Last synced: about 1 month ago
JSON representation
A CPU-optimized local Linux pipeline using OpenAI CV and YOLOv8/ByteTrack to monitor home occupancy via RTSP streams, featuring directional tripwire tracking and a FastAPI query endpoint.
- Host: GitHub
- URL: https://github.com/mrazza/cctv-home-occupancy
- Owner: mrazza
- License: apache-2.0
- Created: 2026-05-23T02:01:52.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-24T04:47:47.000Z (about 1 month ago)
- Last Synced: 2026-05-24T06:20:52.151Z (about 1 month ago)
- Topics: bytetrack, computer-vision, fastapi, home-automation, motion-detection, object-tracking, opencv, rtsp, sqlite, yolov8
- Language: Python
- Homepage:
- Size: 81.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# House Presence Monitoring System (cctv-home-occupancy)
A private, high-performance local Linux pipeline to monitor presence in your home using realtime video streams (e.g. Nest cameras). It operates in a **"Fast & Slow"** fashion to optimize CPU utilization:
1. **Fast Stage (0% CPU idle)**: Continuous, ultra-lightweight pixel differencing with OpenCV.
2. **Slow Stage (Active AI)**: Activates YOLOv8 and ByteTrack to track people crossing virtual tripwires only when motion is detected.
Exposes a FastAPI endpoint that can be directly queried or hooked into a Mattermost Chatbot Slash Command.
---
## 🛠 Features
- **RTSP Input**: Integrated with local WebRTC-to-RTSP bridges (e.g. Scrypted or go2rtc).
- **CPU Optimized**: Uses background subtraction to wake/sleep the deep learning tracking logic.
- **Directional Crossing Math**: Uses geometric intersection and vector cross-product to detect entering vs. leaving.
- **Self-Correcting State Engine**: Maintains transactional SQLite DB representing household occupancy.
- **Queryable API**: FastAPI allows Mattermost bots to query "Is anyone home?" or fetch snapshots of recent entry/exit events.
- **Facial Crop Support**: Automatically isolates crops of faces/bodies for future facial identification.
---
## 📐 Configuring Your Tripwire (Line-Crossing)
Every camera has a unique angle, so you must define the doorway boundary in `src/config.py` using normalized coordinates from `0.0` (top/left) to `1.0` (bottom/right).
### The "Left-Hand Rule" for Directed Vectors
The tripwire is represented as a directed vector starting at Point A $(x_1, y_1)$ and ending at Point B $(x_2, y_2)$.
To determine which side of the line is **Inside** (incrementing occupancy) vs. **Outside** (decrementing occupancy), use the **Left-Hand Rule**:
> **Imagine standing at Point A and looking down the line towards Point B:**
> * Any crossing onto your **Left-hand side** is classified as **Inside (+1 / ENTER)**.
> * Any crossing onto your **Right-hand side** is classified as **Outside (-1 / LEAVE)**.
---
### Concrete Visual Examples (Screen Space)
In screen coordinates, the top-left corner is `(0.0, 0.0)` and the bottom-right corner is `(1.0, 1.0)`. Here is how the line direction maps visually:
#### 1. Horizontal Doorways
* **Drawing from Left to Right:** Point A is Left, Point B is Right.
* Stand at A, look at B: Your Left hand points **downward**.
* 🟢 **Inside (+1 / ENTER)** is visually **below** the line (higher Y values, closer to the bottom of the screen).
* 🔴 **Outside (-1 / LEAVE)** is visually **above** the line (lower Y values, closer to the top of the screen).
* **Drawing from Right to Left:** Point A is Right, Point B is Left.
* Stand at A, look at B: Your Left hand points **upward**.
* 🟢 **Inside (+1 / ENTER)** is visually **above** the line (closer to the top of the screen).
* 🔴 **Outside (-1 / LEAVE)** is visually **below** the line (closer to the bottom of the screen).
#### 2. Vertical Doorways
* **Drawing from Bottom to Top:** Point A is Bottom, Point B is Top.
* Stand at A, look at B: Your Left hand points to the **left**.
* 🟢 **Inside (+1 / ENTER)** is visually to the **Left** of the line (lower X values).
* 🔴 **Outside (-1 / LEAVE)** is visually to the **Right** of the line (higher X values).
* **Drawing from Top to Bottom:** Point A is Top, Point B is Bottom.
* Stand at A, look at B: Your Left hand points to the **right**.
* 🟢 **Inside (+1 / ENTER)** is visually to the **Right** of the line (higher X values).
* 🔴 **Outside (-1 / LEAVE)** is visually to the **Left** of the line (lower X values).
---
## 🚀 Installation & Setup
### 1. Prerequisites
- Linux Server with Python 3.10+ and Docker.
- A local RTSP stream from your Nest Camera using a WebRTC-to-RTSP bridge (e.g., **Scrypted** or **go2rtc**).
### 2. Install Dependencies
```bash
cd sources/mrazza/cctv-home-occupancy
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
### 3. Run Unit and Integration Tests
To make sure all tracking math, state engines, and API endpoints function perfectly:
```bash
PYTHONPATH=src pytest
```
---
## ⚙️ Environment Variables Config
You can customize runtime parameters using environment variables without editing the source code:
| Env Variable | Default Value | Description |
| :--- | :--- | :--- |
| `CCTV_RTSP_URL` | `rtsp://localhost:8554/nest-cam` | The local camera stream URL. |
| `CCTV_FPS_LIMIT` | `10` | Target frames per second to process. |
| `CCTV_MOTION_THRESHOLD` | `0.005` | Percent of changed pixels (0.0 to 1.0) to trigger motion state. |
| `CCTV_MIN_CONTOUR_AREA` | `500` | Minimum pixel area of a moving object. |
| `CCTV_MOTION_COOLDOWN` | `150` | How many frames of silence before shutting off YOLO. |
| `CCTV_DB_PATH` | `db/presence.db` | Path to the SQLite presence database. |
| `CCTV_SNAPSHOT_DIR` | `snapshots` | Folder path where face/body crops are stored. |
---
## 🏃 Running the Application
To start both the API server and the background camera-monitoring pipeline:
```bash
source venv/bin/activate
python run.py --rtsp "rtsp://localhost:8554/nest-cam"
```
### API Endpoints
* **Get Current Status**: `GET http://localhost:8000/status`
* Returns: `{"is_someone_home": true, "current_occupancy": 1, "last_updated": "..."}`
* **Fetch Recent Events**: `GET http://localhost:8000/events?limit=10`
* **Manual Override/Reset**: `POST http://localhost:8000/reset`
* Body: `{"is_someone_home": false, "current_occupancy": 0}`
* **Fetch Event Snapshots**: Files can be served directly from `/snapshots/...` (e.g., `http://localhost:8000/snapshots/enter_id9_20260522_210145_390123.jpg`).
---
## 💬 Mattermost Integration
To let users ask *"Is there anyone in the house?"* inside Mattermost:
1. Go to **Mattermost System Console > Integrations > Slash Commands**.
2. Create a new command (e.g. `/whoshome`).
3. Set the **Request URL** to `http://:8000/status` (or use a reverse proxy like Nginx with Auth).
4. Implement a lightweight middleware/webhook handler or configure your command to parse the FastAPI response and output a friendly markdown message:
```markdown
🟢 **Someone is home.**
* **Current occupancy:** 1 occupant(s)
* **Last transition:** Detected at 2026-05-22 21:01
```