尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
People Counter — Entry / Exit Detection Dashboard
A simple, real-world people counting system that uses a video (uploaded file or
recorded camera footage) to detect people, track them across frames, and count
how many crossed a virtual entry/exit line — all displayed live on a React
dashboard.
Built to be beginner-friendly and easy to explain in a technical interview:
no deep-learning frameworks, no database, no C++ — just OpenCV, Flask, and React.檢視完整 README ↗A simple, real-world people counting system that uses a video (uploaded file or recorded camera footage) to detect people, track them across frames, and count how many crossed a virtual entry/exit line — all displayed live on a React dashboard.
Built to be beginner-friendly and easy to explain in a technical interview: no deep-learning frameworks, no database, no C++ — just OpenCV, Flask, and React.
You upload a video of people walking past a doorway, corridor, or gate. The backend processes the video frame by frame with OpenCV: it detects people, tracks each one across frames, and checks whether they crossed a horizontal "virtual line" drawn across the frame. Crossing the line one way counts as an Entry, crossing it the other way counts as an Exit. The frontend shows the live count and the final annotated video with bounding boxes, IDs, and the counting line burned in.
This is the same basic idea used in:
Ready → Processing → Completed / Error).Frontend
Backend
No database is used — all state (counts, job status) lives in memory in the Flask process, and video files are stored on disk. No C++ code is written; OpenCV's Python bindings are used throughout.
Camera / Uploaded Video
│
▼
Python + OpenCV (backend/video_processor.py)
│
▼
Person Detection (backend/detector.py — HOG + SVM)
│
▼
Person Tracking (backend/tracker.py — centroid tracker)
│
▼
Virtual Entry/Exit Line
│
▼
Entry / Exit Counting (backend/counter.py)
│
▼
Flask REST API (backend/app.py)
│
▼
React + TypeScript Dashboard (frontend/)
backend/detector.py uses OpenCV's built-in HOG (Histogram of Oriented
Gradients) + Linear SVM pedestrian detector — cv2.HOGDescriptor() with
cv2.HOGDescriptor_getDefaultPeopleDetector(). This ships with every OpenCV
install, so there's nothing extra to download or configure.
In plain terms: HOG looks at the pattern of edge directions in small blocks of the image (does the pattern of light/dark edges look like the outline of a walking person?). That pattern is fed into a linear SVM classifier that has already been trained to recognize the general shape of a standing or walking human. It's not a deep neural network — it's a classic, well-documented computer-vision technique that's easy to explain and reason about, which is why it fits the "keep it simple" requirement of this project.
Each detection returns a bounding box (x, y, w, h) around a detected person,
with a confidence weight; low-confidence boxes are filtered out to reduce
false positives.
backend/tracker.py implements a centroid tracker:
This is intentionally simple — no Kalman filters, no deep-learning re-ID — a nearest-neighbour match is enough to track a handful of people moving through a doorway.
backend/counter.py keeps a virtual horizontal line at the middle of the
frame (configurable). For every tracked person, it remembers which side of
the line they were on the last time they were seen:
Above line → Below line = Entry
Below line → Above line = Exit
People Inside = Entry Count − Exit Count
Each crossing is tagged with the tracked person's unique ID plus the direction of that specific crossing, so the same person is never counted twice for the same crossing event even if their centroid jitters near the line for a few frames.
people-counter/
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ ├── VideoUploader.tsx
│ │ │ ├── VideoViewer.tsx
│ │ │ ├── PeopleStats.tsx
│ │ │ ├── ControlButtons.tsx
│ │ │ └── StatusIndicator.tsx
│ │ ├── services/
│ │ │ └── api.ts
│ │ ├── types.ts
│ │ ├── App.tsx
│ │ ├── App.css
│ │ ├── index.css
│ │ └── main.tsx
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ ├── tsconfig.app.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
│
├── backend/
│ ├── app.py
│ ├── detector.py
│ ├── tracker.py
│ ├── counter.py
│ ├── video_processor.py
│ ├── uploads/ (uploaded videos land here; ignored by git)
│ ├── processed/ (annotated output videos; ignored by git)
│ └── requirements.txt
│
├── .gitignore
└── README.md
git clone https://github.com/<your-username>/people-counter.git
cd people-counter
cd backend
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
cd frontend
npm install
cd backend
source venv/bin/activate # if not already active
python3 app.py
The API starts on http://localhost:5000.
In a separate terminal:
cd frontend
npm run dev
The dashboard is available at http://localhost:5173. It talks to the
Flask API at http://localhost:5000 by default — set VITE_API_BASE_URL in a
frontend/.env file if you run the backend somewhere else.
Then in the browser:
.mp4, .avi, .mov,
.mkv, or .webm).Processing to Completed.| Method | Endpoint | Description |
|---|---|---|
| GET | /health | Simple health check. |
| POST | /upload | Upload a video file (multipart/form-data, field video). |
| POST | /process | Start processing an uploaded video ({ "filename": "..." }). |
| GET | /status | Poll current status, progress, and live counts. |
| GET | /processed/<file> | Stream/download the processed output video. |
| POST | /reset | Reset counts and job state back to ready. |
Example status response while processing:
{
"status": "processing",
"progress": 42,
"errorMessage": null,
"entryCount": 3,
"exitCount": 1,
"peopleInside": 2,
"processedVideoReady": false
}
The pipeline was verified end-to-end during development:
tracker.py + counter.py were exercised with synthetic
centroid paths moving across the line in both directions, confirming
correct entry/exit counting and no double-counting.video_processor.py was run against a generated test
video to confirm detection → tracking → counting → annotated video output
runs without errors and produces a valid .mp4./health, /upload, /process, /status,
/processed/<file>, /reset) was exercised with curl, including error
paths — empty upload, missing file, unsupported format, processing a video
that doesn't exist, and downloading a missing processed file.tsc -b type-checks cleanly and npm run build produces a
working production bundle with no errors.To reproduce the manual test flow yourself, run the backend and frontend as
described above and upload any short .mp4 clip of people walking through a
doorway or corridor — the more clearly a full body is visible, the more
reliably the HOG detector will pick it up.
(Add screenshots of the dashboard here once you have real footage —
e.g. docs/screenshot-dashboard.png, docs/screenshot-processing.png.)