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.
Files changed (49) hide show
  1. cvgo-0.1.1/LICENSE +22 -0
  2. cvgo-0.1.1/MANIFEST.in +5 -0
  3. cvgo-0.1.1/PKG-INFO +700 -0
  4. cvgo-0.1.1/PUBLISHING.md +158 -0
  5. cvgo-0.1.1/README.md +674 -0
  6. cvgo-0.1.1/examples/01_camera.py +18 -0
  7. cvgo-0.1.1/examples/02_face_detection.py +25 -0
  8. cvgo-0.1.1/examples/03_face_landmarks.py +25 -0
  9. cvgo-0.1.1/examples/04_face_metrics.py +35 -0
  10. cvgo-0.1.1/examples/05_serial_arduino.py +12 -0
  11. cvgo-0.1.1/examples/06_face_to_arduino.py +33 -0
  12. cvgo-0.1.1/examples/07_drowsiness.py +46 -0
  13. cvgo-0.1.1/examples/08_driver_monitor.py +133 -0
  14. cvgo-0.1.1/examples/09_hand_tracking.py +30 -0
  15. cvgo-0.1.1/examples/10_pose_tracking.py +32 -0
  16. cvgo-0.1.1/examples/11_security_pose.py +34 -0
  17. cvgo-0.1.1/examples/12_object_detection.py +28 -0
  18. cvgo-0.1.1/examples/13_person_security.py +34 -0
  19. cvgo-0.1.1/examples/14_gesture_recognition.py +24 -0
  20. cvgo-0.1.1/examples/15_holistic_tracking.py +22 -0
  21. cvgo-0.1.1/examples/16_selfie_segmentation.py +22 -0
  22. cvgo-0.1.1/examples/17_telegram_security.py +43 -0
  23. cvgo-0.1.1/pyproject.toml +52 -0
  24. cvgo-0.1.1/setup.cfg +4 -0
  25. cvgo-0.1.1/src/cvgo/__init__.py +82 -0
  26. cvgo-0.1.1/src/cvgo/camera.py +127 -0
  27. cvgo-0.1.1/src/cvgo/drawing.py +52 -0
  28. cvgo-0.1.1/src/cvgo/driver.py +434 -0
  29. cvgo-0.1.1/src/cvgo/face.py +242 -0
  30. cvgo-0.1.1/src/cvgo/gesture.py +209 -0
  31. cvgo-0.1.1/src/cvgo/hand.py +330 -0
  32. cvgo-0.1.1/src/cvgo/holistic.py +284 -0
  33. cvgo-0.1.1/src/cvgo/metrics.py +94 -0
  34. cvgo-0.1.1/src/cvgo/models.py +159 -0
  35. cvgo-0.1.1/src/cvgo/object_detection.py +204 -0
  36. cvgo-0.1.1/src/cvgo/pose.py +214 -0
  37. cvgo-0.1.1/src/cvgo/segmentation.py +112 -0
  38. cvgo-0.1.1/src/cvgo/serial_io.py +143 -0
  39. cvgo-0.1.1/src/cvgo/sound.py +68 -0
  40. cvgo-0.1.1/src/cvgo/telegram.py +374 -0
  41. cvgo-0.1.1/src/cvgo/timing.py +106 -0
  42. cvgo-0.1.1/src/cvgo.egg-info/PKG-INFO +700 -0
  43. cvgo-0.1.1/src/cvgo.egg-info/SOURCES.txt +47 -0
  44. cvgo-0.1.1/src/cvgo.egg-info/dependency_links.txt +1 -0
  45. cvgo-0.1.1/src/cvgo.egg-info/requires.txt +8 -0
  46. cvgo-0.1.1/src/cvgo.egg-info/top_level.txt +1 -0
  47. cvgo-0.1.1/tests/test_core.py +117 -0
  48. cvgo-0.1.1/tests/test_extended.py +422 -0
  49. 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
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include LICENSE
3
+ include PUBLISHING.md
4
+ recursive-include examples *.py
5
+
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.