尚未检测到更新。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.)