cvgo 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cvgo-0.1.1/LICENSE +22 -0
- cvgo-0.1.1/MANIFEST.in +5 -0
- cvgo-0.1.1/PKG-INFO +700 -0
- cvgo-0.1.1/PUBLISHING.md +158 -0
- cvgo-0.1.1/README.md +674 -0
- cvgo-0.1.1/examples/01_camera.py +18 -0
- cvgo-0.1.1/examples/02_face_detection.py +25 -0
- cvgo-0.1.1/examples/03_face_landmarks.py +25 -0
- cvgo-0.1.1/examples/04_face_metrics.py +35 -0
- cvgo-0.1.1/examples/05_serial_arduino.py +12 -0
- cvgo-0.1.1/examples/06_face_to_arduino.py +33 -0
- cvgo-0.1.1/examples/07_drowsiness.py +46 -0
- cvgo-0.1.1/examples/08_driver_monitor.py +133 -0
- cvgo-0.1.1/examples/09_hand_tracking.py +30 -0
- cvgo-0.1.1/examples/10_pose_tracking.py +32 -0
- cvgo-0.1.1/examples/11_security_pose.py +34 -0
- cvgo-0.1.1/examples/12_object_detection.py +28 -0
- cvgo-0.1.1/examples/13_person_security.py +34 -0
- cvgo-0.1.1/examples/14_gesture_recognition.py +24 -0
- cvgo-0.1.1/examples/15_holistic_tracking.py +22 -0
- cvgo-0.1.1/examples/16_selfie_segmentation.py +22 -0
- cvgo-0.1.1/examples/17_telegram_security.py +43 -0
- cvgo-0.1.1/pyproject.toml +52 -0
- cvgo-0.1.1/setup.cfg +4 -0
- cvgo-0.1.1/src/cvgo/__init__.py +82 -0
- cvgo-0.1.1/src/cvgo/camera.py +127 -0
- cvgo-0.1.1/src/cvgo/drawing.py +52 -0
- cvgo-0.1.1/src/cvgo/driver.py +434 -0
- cvgo-0.1.1/src/cvgo/face.py +242 -0
- cvgo-0.1.1/src/cvgo/gesture.py +209 -0
- cvgo-0.1.1/src/cvgo/hand.py +330 -0
- cvgo-0.1.1/src/cvgo/holistic.py +284 -0
- cvgo-0.1.1/src/cvgo/metrics.py +94 -0
- cvgo-0.1.1/src/cvgo/models.py +159 -0
- cvgo-0.1.1/src/cvgo/object_detection.py +204 -0
- cvgo-0.1.1/src/cvgo/pose.py +214 -0
- cvgo-0.1.1/src/cvgo/segmentation.py +112 -0
- cvgo-0.1.1/src/cvgo/serial_io.py +143 -0
- cvgo-0.1.1/src/cvgo/sound.py +68 -0
- cvgo-0.1.1/src/cvgo/telegram.py +374 -0
- cvgo-0.1.1/src/cvgo/timing.py +106 -0
- cvgo-0.1.1/src/cvgo.egg-info/PKG-INFO +700 -0
- cvgo-0.1.1/src/cvgo.egg-info/SOURCES.txt +47 -0
- cvgo-0.1.1/src/cvgo.egg-info/dependency_links.txt +1 -0
- cvgo-0.1.1/src/cvgo.egg-info/requires.txt +8 -0
- cvgo-0.1.1/src/cvgo.egg-info/top_level.txt +1 -0
- cvgo-0.1.1/tests/test_core.py +117 -0
- cvgo-0.1.1/tests/test_extended.py +422 -0
- cvgo-0.1.1/tests/test_primitives.py +160 -0
cvgo-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ajang Rahmat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
cvgo-0.1.1/MANIFEST.in
ADDED
cvgo-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cvgo
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Simple Computer Vision for Python
|
|
5
|
+
Author: Ajang Rahmat
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://kelasrobot.com
|
|
8
|
+
Keywords: computer-vision,opencv,mediapipe,arduino,telegram,education
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Education
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: <3.13,>=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy==1.26.4
|
|
19
|
+
Requires-Dist: opencv-contrib-python==4.11.0.86
|
|
20
|
+
Requires-Dist: mediapipe==0.10.21
|
|
21
|
+
Requires-Dist: pyserial>=3.5
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
24
|
+
Requires-Dist: twine>=5; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# CVGO
|
|
28
|
+
|
|
29
|
+
**Simple Computer Vision for Python**
|
|
30
|
+
|
|
31
|
+
CVGO simplifies the repetitive parts of OpenCV and MediaPipe while keeping the
|
|
32
|
+
main program flow visible. Users still write `while True`, read frames, inspect
|
|
33
|
+
detection results, make decisions, and display the GUI.
|
|
34
|
+
|
|
35
|
+
> Simple by default, customizable when needed.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
Once available on PyPI:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install cvgo
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
CVGO V1 pins the core versions that have been tested:
|
|
46
|
+
|
|
47
|
+
| Package | Version |
|
|
48
|
+
|---|---|
|
|
49
|
+
| CVGO | `0.1.1` |
|
|
50
|
+
| OpenCV Contrib | `4.11.0.86` |
|
|
51
|
+
| NumPy | `1.26.4` |
|
|
52
|
+
| MediaPipe | `0.10.21` |
|
|
53
|
+
|
|
54
|
+
The OpenCV package used is `opencv-contrib-python` to avoid installing two
|
|
55
|
+
separate `cv2` variants alongside MediaPipe dependencies.
|
|
56
|
+
|
|
57
|
+
Use Python 3.10, 3.11, or 3.12.
|
|
58
|
+
|
|
59
|
+
It is recommended to install CVGO in a dedicated virtual environment:
|
|
60
|
+
|
|
61
|
+
```powershell
|
|
62
|
+
py -3.11 -m venv .venv-cvgo
|
|
63
|
+
.venv-cvgo\Scripts\Activate.ps1
|
|
64
|
+
python -m pip install --upgrade pip
|
|
65
|
+
python -m pip install cvgo
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
In a new virtual environment, `pip` installs dependencies once. If the
|
|
69
|
+
installation command is run again in the same environment, matching packages are
|
|
70
|
+
reported as `Requirement already satisfied`.
|
|
71
|
+
|
|
72
|
+
Do not install `opencv-python`, `opencv-python-headless`, or other OpenCV
|
|
73
|
+
variants alongside `opencv-contrib-python`. They all provide the same `cv2`
|
|
74
|
+
module.
|
|
75
|
+
|
|
76
|
+
`ObjectDetector` and `GestureRecognizer` use official MediaPipe models that are
|
|
77
|
+
downloaded automatically on first use. The computer only needs internet access
|
|
78
|
+
for the first download; afterward, the model is reused from cache.
|
|
79
|
+
|
|
80
|
+
## Import
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import cvgo as go
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
All components can also be imported directly:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from cvgo import Camera, ObjectDetector, Telegram
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## CVGO V1 Features
|
|
93
|
+
|
|
94
|
+
| Feature | Main API | Output |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| Camera and GUI | `Camera` | OpenCV frames |
|
|
97
|
+
| Face detection | `FaceDetector` | Face boxes |
|
|
98
|
+
| Face landmarks | `FaceLandmarks` | Face landmarks and metrics |
|
|
99
|
+
| Hand tracking | `HandTracker` | 21 landmarks per hand |
|
|
100
|
+
| Pose tracking | `PoseTracker` | 33 body landmarks |
|
|
101
|
+
| Holistic tracking | `HolisticTracker` | Face, pose, and both hands |
|
|
102
|
+
| Gesture | `GestureRecognizer` | Gesture, score, and landmarks |
|
|
103
|
+
| Object detection | `ObjectDetector` | Labels, scores, and object boxes |
|
|
104
|
+
| Human segmentation | `SelfieSegmenter` | Human mask and background |
|
|
105
|
+
| Driver monitor | Modular components | Drowsiness, head direction, and alarms |
|
|
106
|
+
| Arduino | `Serial` | Serial communication |
|
|
107
|
+
| Telegram | `Telegram` | Text messages and photos from camera frames |
|
|
108
|
+
|
|
109
|
+
This is the full coverage of CVGO V1 for camera and learning projects.
|
|
110
|
+
MediaPipe features outside this scope can still be added in later versions without
|
|
111
|
+
changing the main API pattern.
|
|
112
|
+
|
|
113
|
+
## Python Naming Style
|
|
114
|
+
|
|
115
|
+
CVGO follows common Python naming conventions (PEP 8):
|
|
116
|
+
|
|
117
|
+
- classes use `PascalCase`: `HandTracker`, `PoseTracker`;
|
|
118
|
+
- functions and methods use `snake_case`: `read_fps()`, `put_text()`;
|
|
119
|
+
- constants use `UPPER_CASE`: `BIT_DROWSY`, `LEFT_WRIST`.
|
|
120
|
+
|
|
121
|
+
So use `read_fps()`, not `readFPS()`. Since the object is already named `FPS`,
|
|
122
|
+
the shortest form is `fps.read()`. `fps.read_fps()` remains available as a more
|
|
123
|
+
explicit alias.
|
|
124
|
+
|
|
125
|
+
## Simple Defaults
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
camera = go.Camera()
|
|
129
|
+
faces = go.FaceDetector()
|
|
130
|
+
landmarks = go.FaceLandmarks()
|
|
131
|
+
hands = go.HandTracker()
|
|
132
|
+
pose = go.PoseTracker()
|
|
133
|
+
objects = go.ObjectDetector()
|
|
134
|
+
arduino = go.Serial()
|
|
135
|
+
timer = go.Timer()
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Main defaults:
|
|
139
|
+
|
|
140
|
+
| Component | Default |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `Camera()` | Camera `0` |
|
|
143
|
+
| `FaceDetector()` | Maximum one face |
|
|
144
|
+
| `FaceLandmarks()` | Maximum one face |
|
|
145
|
+
| `HandTracker()` | Maximum two hands |
|
|
146
|
+
| `PoseTracker()` | One main pose |
|
|
147
|
+
| `HolisticTracker()` | One main person, 543 landmarks |
|
|
148
|
+
| `GestureRecognizer()` | Maximum two hands |
|
|
149
|
+
| `ObjectDetector()` | Maximum 10 objects, confidence `0.5` |
|
|
150
|
+
| `SelfieSegmenter()` | Landscape model for webcams |
|
|
151
|
+
| `Serial()` | Automatic port, `9600` baud |
|
|
152
|
+
| `Telegram()` | Environment-based configuration, 30-second cooldown |
|
|
153
|
+
| `Timer()` | One-second duration |
|
|
154
|
+
| `Smoother()` | Alpha `0.45` |
|
|
155
|
+
|
|
156
|
+
Only set parameters when you want to change the default behavior:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
camera = go.Camera(1, width=1280, height=720)
|
|
160
|
+
arduino = go.Serial("COM5", baud=115200)
|
|
161
|
+
timer = go.Timer(1.5)
|
|
162
|
+
hands = go.HandTracker(max_hands=1, detection_confidence=0.7)
|
|
163
|
+
pose = go.PoseTracker(model_complexity=0)
|
|
164
|
+
objects = go.ObjectDetector(confidence=0.7, allow=["person"])
|
|
165
|
+
telegram = go.Telegram(cooldown=60)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Camera
|
|
169
|
+
|
|
170
|
+
By default, CVGO leaves OpenCV to choose the best camera backend (`CAP_ANY`). A
|
|
171
|
+
custom backend can still be passed using the `backend` parameter.
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
import cvgo as go
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
camera = go.Camera()
|
|
178
|
+
|
|
179
|
+
while True:
|
|
180
|
+
frame = camera.read()
|
|
181
|
+
|
|
182
|
+
if frame is None:
|
|
183
|
+
break
|
|
184
|
+
|
|
185
|
+
if not camera.show(frame):
|
|
186
|
+
break
|
|
187
|
+
|
|
188
|
+
camera.close()
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Press `q` to quit.
|
|
192
|
+
|
|
193
|
+
## Face Detection
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
import cvgo as go
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
camera = go.Camera()
|
|
200
|
+
detector = go.FaceDetector()
|
|
201
|
+
|
|
202
|
+
while True:
|
|
203
|
+
frame = camera.read()
|
|
204
|
+
|
|
205
|
+
if frame is None:
|
|
206
|
+
break
|
|
207
|
+
|
|
208
|
+
faces = detector.detect(frame)
|
|
209
|
+
|
|
210
|
+
for face in faces:
|
|
211
|
+
face.draw(frame)
|
|
212
|
+
|
|
213
|
+
if not camera.show(frame):
|
|
214
|
+
break
|
|
215
|
+
|
|
216
|
+
camera.close()
|
|
217
|
+
detector.close()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Face Landmarks and Metrics
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
import cvgo as go
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
camera = go.Camera()
|
|
227
|
+
landmarker = go.FaceLandmarks()
|
|
228
|
+
|
|
229
|
+
while True:
|
|
230
|
+
frame = camera.read()
|
|
231
|
+
|
|
232
|
+
if frame is None:
|
|
233
|
+
break
|
|
234
|
+
|
|
235
|
+
faces = landmarker.detect(frame)
|
|
236
|
+
|
|
237
|
+
if faces:
|
|
238
|
+
face = faces[0]
|
|
239
|
+
|
|
240
|
+
ear = go.eye_ratio(face)
|
|
241
|
+
yaw = go.yaw_ratio(face)
|
|
242
|
+
pitch = go.pitch_ratio(face)
|
|
243
|
+
|
|
244
|
+
go.put_text(frame, f"EAR: {ear:.3f}")
|
|
245
|
+
face.draw(frame)
|
|
246
|
+
|
|
247
|
+
if not camera.show(frame):
|
|
248
|
+
break
|
|
249
|
+
|
|
250
|
+
camera.close()
|
|
251
|
+
landmarker.close()
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Hand Tracking
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
import cvgo as go
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
camera = go.Camera()
|
|
261
|
+
tracker = go.HandTracker()
|
|
262
|
+
|
|
263
|
+
while True:
|
|
264
|
+
frame = camera.read()
|
|
265
|
+
|
|
266
|
+
if frame is None:
|
|
267
|
+
break
|
|
268
|
+
|
|
269
|
+
hands = tracker.detect(frame)
|
|
270
|
+
|
|
271
|
+
for hand in hands:
|
|
272
|
+
hand.draw(frame)
|
|
273
|
+
|
|
274
|
+
if not camera.show(frame):
|
|
275
|
+
break
|
|
276
|
+
|
|
277
|
+
camera.close()
|
|
278
|
+
tracker.close()
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Each `Hand` has 21 points, `handedness`, `confidence`, `box()`, and raw MediaPipe
|
|
282
|
+
results via `raw`. Named landmarks make customization clearer:
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
tip = hand.point(go.HandLandmark.INDEX_FINGER_TIP)
|
|
286
|
+
x, y = tip.pixel(frame)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
OpenCV gives webcam frames without mirroring, so `HandTracker` automatically
|
|
290
|
+
adjusts left/right labels by default. If the frame is already flipped horizontally
|
|
291
|
+
before detection, use `go.HandTracker(mirrored=True)`.
|
|
292
|
+
|
|
293
|
+
## Pose Tracking
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
import cvgo as go
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
camera = go.Camera()
|
|
300
|
+
tracker = go.PoseTracker()
|
|
301
|
+
|
|
302
|
+
while True:
|
|
303
|
+
frame = camera.read()
|
|
304
|
+
|
|
305
|
+
if frame is None:
|
|
306
|
+
break
|
|
307
|
+
|
|
308
|
+
pose = tracker.detect(frame)
|
|
309
|
+
|
|
310
|
+
if pose:
|
|
311
|
+
pose.draw(frame)
|
|
312
|
+
|
|
313
|
+
if not camera.show(frame):
|
|
314
|
+
break
|
|
315
|
+
|
|
316
|
+
camera.close()
|
|
317
|
+
tracker.close()
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
`PoseTracker` produces 33 body landmarks and world coordinates through
|
|
321
|
+
`pose.world_points`. Example access to a point:
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
shoulder = pose.point(go.PoseLandmark.LEFT_SHOULDER)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`pose is not None` means the model found a sufficiently visible body pose. This can
|
|
328
|
+
be used as a signal for the presence of one main person, but it is not a general
|
|
329
|
+
person detector or a multi-person counter. For distant CCTV, multi-person, or
|
|
330
|
+
crowd counting scenarios, use the object detection model.
|
|
331
|
+
|
|
332
|
+
## FPS
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
fps = go.FPS()
|
|
336
|
+
|
|
337
|
+
while True:
|
|
338
|
+
frame = camera.read()
|
|
339
|
+
value = fps.read()
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
The value is updated every second by default. The interval can be changed with
|
|
343
|
+
`go.FPS(update_every=0.5)`.
|
|
344
|
+
|
|
345
|
+
## Object Detection
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
import cvgo as go
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
camera = go.Camera()
|
|
352
|
+
detector = go.ObjectDetector()
|
|
353
|
+
|
|
354
|
+
while True:
|
|
355
|
+
frame = camera.read()
|
|
356
|
+
|
|
357
|
+
if frame is None:
|
|
358
|
+
break
|
|
359
|
+
|
|
360
|
+
objects = detector.detect(frame)
|
|
361
|
+
|
|
362
|
+
for item in objects:
|
|
363
|
+
item.draw(frame)
|
|
364
|
+
|
|
365
|
+
if not camera.show(frame):
|
|
366
|
+
break
|
|
367
|
+
|
|
368
|
+
camera.close()
|
|
369
|
+
detector.close()
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Each `DetectedObject` has `label`, `score`, `box`, `is_person`, and raw results via
|
|
373
|
+
`raw`. For person detection specifically:
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
detector = go.ObjectDetector(allow=["person"])
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The official MediaPipe EfficientDet-Lite0 model is downloaded automatically once
|
|
380
|
+
on first use. After that, the model is read from cache. Custom models can still be
|
|
381
|
+
used:
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
detector = go.ObjectDetector("models/custom_model.tflite")
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
The model can also be prepared in advance:
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
go.download_model("object_detection")
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
To process separate images instead of sequential video frames, use
|
|
394
|
+
`go.ObjectDetector(stream=False)`.
|
|
395
|
+
|
|
396
|
+
## Gesture Recognition
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
import cvgo as go
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
camera = go.Camera()
|
|
403
|
+
recognizer = go.GestureRecognizer()
|
|
404
|
+
|
|
405
|
+
while True:
|
|
406
|
+
frame = camera.read()
|
|
407
|
+
|
|
408
|
+
if frame is None:
|
|
409
|
+
break
|
|
410
|
+
|
|
411
|
+
gestures = recognizer.detect(frame)
|
|
412
|
+
|
|
413
|
+
for gesture in gestures:
|
|
414
|
+
gesture.draw(frame)
|
|
415
|
+
|
|
416
|
+
if not camera.show(frame):
|
|
417
|
+
break
|
|
418
|
+
|
|
419
|
+
camera.close()
|
|
420
|
+
recognizer.close()
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The default model recognizes `Closed_Fist`, `Open_Palm`, `Pointing_Up`,
|
|
424
|
+
`Thumb_Down`, `Thumb_Up`, `Victory`, and `ILoveYou`. Each result also exposes
|
|
425
|
+
`gesture.hand`, `gesture.score`, and raw landmarks for custom logic.
|
|
426
|
+
|
|
427
|
+
Use `go.GestureRecognizer(stream=False)` for static images that are not part of a
|
|
428
|
+
continuous video stream.
|
|
429
|
+
|
|
430
|
+
## Holistic Tracking
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
import cvgo as go
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
camera = go.Camera()
|
|
437
|
+
tracker = go.HolisticTracker()
|
|
438
|
+
|
|
439
|
+
while True:
|
|
440
|
+
frame = camera.read()
|
|
441
|
+
|
|
442
|
+
if frame is None:
|
|
443
|
+
break
|
|
444
|
+
|
|
445
|
+
result = tracker.detect(frame)
|
|
446
|
+
result.draw(frame)
|
|
447
|
+
|
|
448
|
+
if not camera.show(frame):
|
|
449
|
+
break
|
|
450
|
+
|
|
451
|
+
camera.close()
|
|
452
|
+
tracker.close()
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The result parts can still be accessed directly through `result.face`,
|
|
456
|
+
`result.pose`, `result.left_hand`, and `result.right_hand`.
|
|
457
|
+
|
|
458
|
+
## Selfie Segmentation
|
|
459
|
+
|
|
460
|
+
```python
|
|
461
|
+
import cvgo as go
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
camera = go.Camera()
|
|
465
|
+
segmenter = go.SelfieSegmenter()
|
|
466
|
+
|
|
467
|
+
while True:
|
|
468
|
+
frame = camera.read()
|
|
469
|
+
|
|
470
|
+
if frame is None:
|
|
471
|
+
break
|
|
472
|
+
|
|
473
|
+
result = segmenter.segment(frame)
|
|
474
|
+
frame = result.blur(frame)
|
|
475
|
+
|
|
476
|
+
if not camera.show(frame):
|
|
477
|
+
break
|
|
478
|
+
|
|
479
|
+
camera.close()
|
|
480
|
+
segmenter.close()
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Replace the background with a color or image:
|
|
484
|
+
|
|
485
|
+
```python
|
|
486
|
+
frame = result.apply(frame, background=(40, 40, 40))
|
|
487
|
+
frame = result.apply(frame, background=background_image)
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
## Condition Timer
|
|
491
|
+
|
|
492
|
+
`Timer` becomes active when a condition remains true for the configured duration.
|
|
493
|
+
|
|
494
|
+
```python
|
|
495
|
+
eye_timer = go.Timer(1.5)
|
|
496
|
+
|
|
497
|
+
eyes_closed = ear < 0.20
|
|
498
|
+
drowsy = eye_timer.check(eyes_closed)
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
When `eyes_closed` becomes false again, the timer resets automatically.
|
|
502
|
+
|
|
503
|
+
## Easy-to-Understand Drowsiness Detection
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
import cvgo as go
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
EAR_THRESHOLD = 0.20
|
|
510
|
+
|
|
511
|
+
camera = go.Camera()
|
|
512
|
+
landmarker = go.FaceLandmarks()
|
|
513
|
+
eye_timer = go.Timer(1.5)
|
|
514
|
+
ear_smoother = go.Smoother()
|
|
515
|
+
alarm = go.Alarm()
|
|
516
|
+
|
|
517
|
+
while True:
|
|
518
|
+
frame = camera.read()
|
|
519
|
+
|
|
520
|
+
if frame is None:
|
|
521
|
+
break
|
|
522
|
+
|
|
523
|
+
faces = landmarker.detect(frame)
|
|
524
|
+
drowsy = False
|
|
525
|
+
|
|
526
|
+
if faces:
|
|
527
|
+
face = faces[0]
|
|
528
|
+
ear = ear_smoother.update(go.eye_ratio(face))
|
|
529
|
+
drowsy = eye_timer.check(ear < EAR_THRESHOLD)
|
|
530
|
+
|
|
531
|
+
status = "DROWSY" if drowsy else "NORMAL"
|
|
532
|
+
color = (0, 0, 255) if drowsy else (0, 255, 0)
|
|
533
|
+
|
|
534
|
+
go.put_text(frame, f"Status: {status}", color=color)
|
|
535
|
+
go.put_text(frame, f"EAR: {ear:.3f}", (20, 70))
|
|
536
|
+
face.draw(frame, color=color)
|
|
537
|
+
else:
|
|
538
|
+
eye_timer.reset()
|
|
539
|
+
ear_smoother.reset()
|
|
540
|
+
|
|
541
|
+
alarm.trigger(drowsy)
|
|
542
|
+
|
|
543
|
+
if not camera.show(frame):
|
|
544
|
+
break
|
|
545
|
+
|
|
546
|
+
camera.close()
|
|
547
|
+
landmarker.close()
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Bagian penting tetap terlihat: EAR, threshold, smoothing, timer, status, alarm,
|
|
551
|
+
dan GUI.
|
|
552
|
+
|
|
553
|
+
## Serial Arduino
|
|
554
|
+
|
|
555
|
+
```python
|
|
556
|
+
import cvgo as go
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
arduino = go.Serial()
|
|
560
|
+
|
|
561
|
+
if arduino.connected:
|
|
562
|
+
arduino.send("1")
|
|
563
|
+
|
|
564
|
+
arduino.close()
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
## Telegram
|
|
568
|
+
|
|
569
|
+
Buat bot melalui `@BotFather`, lalu simpan token dan chat ID di environment
|
|
570
|
+
variable. Jangan menulis token asli di source code atau repository.
|
|
571
|
+
|
|
572
|
+
Windows PowerShell:
|
|
573
|
+
|
|
574
|
+
```powershell
|
|
575
|
+
$env:CVGO_TELEGRAM_TOKEN="TOKEN_DARI_BOTFATHER"
|
|
576
|
+
$env:CVGO_TELEGRAM_CHAT_ID="CHAT_ID"
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Linux/macOS:
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
export CVGO_TELEGRAM_TOKEN="TOKEN_DARI_BOTFATHER"
|
|
583
|
+
export CVGO_TELEGRAM_CHAT_ID="CHAT_ID"
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
Jika chat ID belum diketahui, kirim `/start` ke bot lalu jalankan:
|
|
587
|
+
|
|
588
|
+
```python
|
|
589
|
+
import cvgo as go
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
telegram = go.Telegram(token="TOKEN_DARI_BOTFATHER")
|
|
593
|
+
print(telegram.find_chat_id())
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
Mengirim teks dan frame OpenCV:
|
|
597
|
+
|
|
598
|
+
```python
|
|
599
|
+
telegram = go.Telegram()
|
|
600
|
+
|
|
601
|
+
telegram.send_message("CVGO aktif")
|
|
602
|
+
telegram.send_photo(
|
|
603
|
+
frame,
|
|
604
|
+
"Peringatan: orang terdeteksi.",
|
|
605
|
+
key="security",
|
|
606
|
+
)
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
`send_photo()` menerima frame OpenCV, bytes, atau path file gambar. Cooldown
|
|
610
|
+
default 30 detik mencegah satu kondisi mengirim terlalu banyak foto. Gunakan
|
|
611
|
+
`key` berbeda untuk setiap jenis peringatan atau ubah dengan
|
|
612
|
+
`go.Telegram(cooldown=60)`. Status pengiriman berupa `True`/`False`; detail
|
|
613
|
+
kegagalan tersedia melalui `telegram.last_error`.
|
|
614
|
+
|
|
615
|
+
Pada proyek deteksi kantuk, pemakaiannya tetap sederhana:
|
|
616
|
+
|
|
617
|
+
```python
|
|
618
|
+
if drowsy:
|
|
619
|
+
telegram.send_photo(
|
|
620
|
+
frame,
|
|
621
|
+
"Peringatan: pengemudi mengantuk.",
|
|
622
|
+
key="drowsy",
|
|
623
|
+
)
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Contoh lengkap deteksi orang dan pengiriman foto berada di
|
|
627
|
+
`examples/17_telegram_security.py`.
|
|
628
|
+
|
|
629
|
+
## Proyek akhir Driver Monitor
|
|
630
|
+
|
|
631
|
+
Contoh lengkap proyek akhir berada di:
|
|
632
|
+
|
|
633
|
+
```text
|
|
634
|
+
examples/08_driver_monitor.py
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Proyek tersebut menggabungkan:
|
|
638
|
+
|
|
639
|
+
- EAR dan smoothing;
|
|
640
|
+
- deteksi noleh serta tunduk;
|
|
641
|
+
- timer untuk setiap kondisi;
|
|
642
|
+
- deteksi wajah hilang;
|
|
643
|
+
- bitmask serial Arduino;
|
|
644
|
+
- foto peringatan Telegram dapat ditambahkan dengan `go.Telegram()`;
|
|
645
|
+
- alarm suara;
|
|
646
|
+
- status dan nilai sensor pada GUI;
|
|
647
|
+
- penghitung FPS.
|
|
648
|
+
|
|
649
|
+
Algoritmanya disusun dari komponen kecil CVGO, bukan satu fungsi instan.
|
|
650
|
+
|
|
651
|
+
## Shortcut opsional
|
|
652
|
+
|
|
653
|
+
`DriverMonitor` tetap tersedia bagi pengguna yang membutuhkan prototipe cepat:
|
|
654
|
+
|
|
655
|
+
```python
|
|
656
|
+
from cvgo import DriverMonitor
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Contoh pembelajaran utama tidak menggunakannya agar algoritma tetap terlihat.
|
|
660
|
+
|
|
661
|
+
## Daftar contoh
|
|
662
|
+
|
|
663
|
+
```text
|
|
664
|
+
examples/
|
|
665
|
+
├── 01_camera.py
|
|
666
|
+
├── 02_face_detection.py
|
|
667
|
+
├── 03_face_landmarks.py
|
|
668
|
+
├── 04_face_metrics.py
|
|
669
|
+
├── 05_serial_arduino.py
|
|
670
|
+
├── 06_face_to_arduino.py
|
|
671
|
+
├── 07_drowsiness.py
|
|
672
|
+
├── 08_driver_monitor.py
|
|
673
|
+
├── 09_hand_tracking.py
|
|
674
|
+
├── 10_pose_tracking.py
|
|
675
|
+
├── 11_security_pose.py
|
|
676
|
+
├── 12_object_detection.py
|
|
677
|
+
├── 13_person_security.py
|
|
678
|
+
├── 14_gesture_recognition.py
|
|
679
|
+
├── 15_holistic_tracking.py
|
|
680
|
+
├── 16_selfie_segmentation.py
|
|
681
|
+
└── 17_telegram_security.py
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
## Pengembangan lokal
|
|
685
|
+
|
|
686
|
+
```bash
|
|
687
|
+
pip install -e .
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
Untuk alat build dan publikasi:
|
|
691
|
+
|
|
692
|
+
```bash
|
|
693
|
+
pip install -e ".[dev]"
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
Panduan TestPyPI dan PyPI tersedia di [`PUBLISHING.md`](PUBLISHING.md).
|
|
697
|
+
|
|
698
|
+
## Lisensi
|
|
699
|
+
|
|
700
|
+
MIT License.
|