sciveo 0.1.58__tar.gz → 0.1.60__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.
- {sciveo-0.1.58 → sciveo-0.1.60}/PKG-INFO +88 -14
- {sciveo-0.1.58 → sciveo-0.1.60}/README.md +87 -13
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/cli.py +6 -4
- sciveo-0.1.60/sciveo/media/capture/cam.py +156 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/tools/video_interactive.py +1 -1
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/embeddings.py +4 -1
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/video/description.py +1 -0
- sciveo-0.1.60/sciveo/tools/aws/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/configuration.py +1 -0
- sciveo-0.1.60/sciveo/tools/draw/__init__.py +0 -0
- sciveo-0.1.60/sciveo/tools/draw/contours.py +147 -0
- sciveo-0.1.60/sciveo/version.py +2 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/PKG-INFO +88 -14
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/SOURCES.txt +5 -1
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/requires.txt +2 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/setup.py +1 -1
- sciveo-0.1.58/sciveo/version.py +0 -2
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/api/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/api/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/api/predictors.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/api/server.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/api/upload.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/common/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/common/configuration.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/common/model.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/common/optimizers.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/common/sampling.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/content/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/content/dataset.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/content/experiment.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/content/project.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/content/runner.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/__init__.py +0 -0
- {sciveo-0.1.58/sciveo/media/ml → sciveo-0.1.60/sciveo/media/capture}/__init__.py +0 -0
- {sciveo-0.1.58/sciveo/media/tools → sciveo-0.1.60/sciveo/media/capture}/nvr.py +0 -0
- {sciveo-0.1.58/sciveo/media/ml/encoders → sciveo-0.1.60/sciveo/media/ml}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/base.py +0 -0
- {sciveo-0.1.58/sciveo/media/ml/nlp → sciveo-0.1.60/sciveo/media/ml/encoders}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/encoders/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/encoders/normalizer.py +0 -0
- {sciveo-0.1.58/sciveo/media/ml/time_series → sciveo-0.1.60/sciveo/media/ml/nlp}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/nlp/search.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines → sciveo-0.1.60/sciveo/media/ml/time_series}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/time_series/dataset.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/time_series/predictor.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/time_series/trainer.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/ml/time_series/window_generator.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/layouts → sciveo-0.1.60/sciveo/media/pipelines}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/job_daemon.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/postprocessors → sciveo-0.1.60/sciveo/media/pipelines/layouts}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/layouts/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/pipeline.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors → sciveo-0.1.60/sciveo/media/pipelines/postprocessors}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/postprocessors/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/postprocessors/default.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/audio → sciveo-0.1.60/sciveo/media/pipelines/processors}/__init__.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/file → sciveo-0.1.60/sciveo/media/pipelines/processors/audio}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/audio/audio.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/audio/audio_extractor_process.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/aws.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/base.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/image → sciveo-0.1.60/sciveo/media/pipelines/processors/file}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/file/archive.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/nlp → sciveo-0.1.60/sciveo/media/pipelines/processors/image}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/album.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/album_in_image.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/depth_esimation.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/embeddings.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/filters.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/generators.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/histogram.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/mask.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/object_detection.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/resize.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/segmentation.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/image/watermark.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/media_info.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/sci → sciveo-0.1.60/sciveo/media/pipelines/processors/nlp}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/nlp/address.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/qr.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/sci/time_series → sciveo-0.1.60/sciveo/media/pipelines/processors/sci}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/sci/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/sci/dataset.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/processors/video → sciveo-0.1.60/sciveo/media/pipelines/processors/sci/time_series}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/sci/time_series/predictor.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/sci/time_series/trainer.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/tpu_base.py +0 -0
- {sciveo-0.1.58/sciveo/media/pipelines/web → sciveo-0.1.60/sciveo/media/pipelines/processors/video}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/generators.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/motion_detection.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/resize.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/video_album.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/video_frames.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/processors/video/video_resample.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/queues.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/server.py +0 -0
- {sciveo-0.1.58/sciveo/media/tools → sciveo-0.1.60/sciveo/media/pipelines/web}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/media/pipelines/web/server.py +0 -0
- {sciveo-0.1.58/sciveo/ml → sciveo-0.1.60/sciveo/media/tools}/__init__.py +0 -0
- {sciveo-0.1.58/sciveo/ml/dataset → sciveo-0.1.60/sciveo/ml}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/base.py +0 -0
- {sciveo-0.1.58/sciveo/ml/evaluation → sciveo-0.1.60/sciveo/ml/dataset}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/dataset/object_detection.py +0 -0
- {sciveo-0.1.58/sciveo/ml/images → sciveo-0.1.60/sciveo/ml/evaluation}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/evaluation/markdown.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/evaluation/object_detection.py +0 -0
- {sciveo-0.1.58/sciveo/ml/nlp → sciveo-0.1.60/sciveo/ml/images}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/base.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/description.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/object_detection.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/tools.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/images/transformers.py +0 -0
- {sciveo-0.1.58/sciveo/ml/nlp/tokenizers → sciveo-0.1.60/sciveo/ml/nlp}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/nlp/embeddings.py +0 -0
- {sciveo-0.1.58/sciveo/ml/video → sciveo-0.1.60/sciveo/ml/nlp/tokenizers}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/ml/nlp/tokenizers/bpe.py +0 -0
- {sciveo-0.1.58/sciveo/monitoring → sciveo-0.1.60/sciveo/ml/video}/__init__.py +0 -0
- {sciveo-0.1.58/sciveo/monitoring/watchdog → sciveo-0.1.60/sciveo/monitoring}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/monitoring/monitor.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/monitoring/start.py +0 -0
- {sciveo-0.1.58/sciveo/network → sciveo-0.1.60/sciveo/monitoring/watchdog}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/monitoring/watchdog/base.py +0 -0
- {sciveo-0.1.58/sciveo/tools → sciveo-0.1.60/sciveo/network}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/network/camera.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/network/sniffer.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/network/tools.py +0 -0
- {sciveo-0.1.58/sciveo/tools/aws → sciveo-0.1.60/sciveo/tools}/__init__.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/array.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/aws/priority_queue.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/aws/s3.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/common.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/complexity.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/compress.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/crypto.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/daemon.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/formating.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/hardware.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/http.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/logger.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/os.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/queue.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/random.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/remote.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/simple_counter.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/synchronized.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo/tools/timers.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/dependency_links.txt +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/entry_points.txt +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/sciveo.egg-info/top_level.txt +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/setup.cfg +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_complexity.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_compress.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_configuration.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_crypto.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_eval_markdown.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_ml_datasets.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_monitoring.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_runner.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_sampling.py +0 -0
- {sciveo-0.1.58 → sciveo-0.1.60}/test/test_tokenizers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sciveo
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.60
|
|
4
4
|
Description-Content-Type: text/markdown
|
|
5
5
|
Provides-Extra: mon
|
|
6
6
|
Provides-Extra: net
|
|
@@ -12,17 +12,90 @@ Provides-Extra: ml
|
|
|
12
12
|
|
|
13
13
|
# SCIVEO - ML/AI and Scientific tools
|
|
14
14
|
|
|
15
|
+
## Monitoring ML Infrastructure
|
|
16
|
+
sciveo monitoring of (ML) machines' CPU/RAM/GPU/NET/DISK/TEMP etc.
|
|
17
|
+
It is very easy to start and use with a single command line.
|
|
18
|
+
|
|
19
|
+
- **Monitoring** of current machine with sampling period of 60 seconds
|
|
20
|
+
```shell
|
|
21
|
+
sciveo monitor --period 60
|
|
22
|
+
```
|
|
23
|
+
- **Monitoring** of current machine, logging the samples to local file (in this case the ./sciveo_monitor.json default name when dir path is used)
|
|
24
|
+
```shell
|
|
25
|
+
sciveo monitor --period 120 --output-path ./
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The monitor client is sendind the monitored samples to remote [sciveo](https://sciveo.com) api (init config located in ~/.sciveo/)
|
|
29
|
+
|
|
30
|
+
### Watchdog monitoring with action
|
|
31
|
+
- **Memory usage** watchdog for 90% max memory, measure every 10 seconds and execute "<some command to handle the high memory event>"
|
|
32
|
+
```shell
|
|
33
|
+
sciveo watchdog --src memory --threshold 90 --period 10 --execute "<some command to handle the high memory event>"
|
|
34
|
+
```
|
|
35
|
+
- **Disk usage** watchdog for 80% max disk usage on /some/path/to/watch path, measure every 600 seconds and execute "<some command to handle the high disk usage event>".
|
|
36
|
+
```shell
|
|
37
|
+
sciveo watchdog --src disk --input-path "/some/path/to/watch" --threshold 80 --period 600 --execute "find /some/path/to/watch -type f -mtime +1"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Network tools
|
|
42
|
+
|
|
43
|
+
- **Network Scan** Networks of hosts to scan for a single port
|
|
44
|
+
```shell
|
|
45
|
+
sciveo scan --port 22
|
|
46
|
+
|
|
47
|
+
sciveo scan --net 192.168.0.0/24 --port 22 --timeout 0.5
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **Network Scan** Single Host list of ports to scan
|
|
51
|
+
```shell
|
|
52
|
+
sciveo scan --host 192.168.0.10
|
|
53
|
+
|
|
54
|
+
sciveo scan --host 192.168.0.10 --ports [443,80]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Remote network video recorder
|
|
58
|
+
|
|
59
|
+
- **NVR** RTSP cams video recorder
|
|
60
|
+
```shell
|
|
61
|
+
sciveo nvr --input-path cams.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
where cams.json has the cam and nvr configuration like
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"video_retention_period": 5,
|
|
68
|
+
"max_video_len": 60,
|
|
69
|
+
"transport": "tcp",
|
|
70
|
+
"path": {
|
|
71
|
+
"tmp": "tmp/nvr/tmp",
|
|
72
|
+
"video": "tmp/nvr/video"
|
|
73
|
+
},
|
|
74
|
+
"cam": {
|
|
75
|
+
"cam_livingroom": {
|
|
76
|
+
"url": "rtsp://192.168.1.11/stream1"
|
|
77
|
+
},
|
|
78
|
+
"cam_kitchen": {
|
|
79
|
+
"url": "rtsp://rtsp://192.168.1.12"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Media pipelines processing worker
|
|
87
|
+
- **Media Pipelines processing** service
|
|
88
|
+
```shell
|
|
89
|
+
sciveo media-server
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
|
|
15
93
|
## Experiments Management Client
|
|
16
94
|
`sciveo` is a Python library that serves as a client for managing machine learning and scientific experiments on the sciveo.com platform. This library provides a convenient interface to interact with the sciveo.com API, enabling users to organize, track, and analyze their experiments efficiently.
|
|
17
95
|
There are few configuration params samplers, which allows easy parameter tuning. The "auto" sampler perhaps is the easiest to use, but also
|
|
18
96
|
"random" and "grid" ones are available.
|
|
19
97
|
|
|
20
|
-
|
|
21
|
-
There is also the sciveo.monitor() which will start monitoring machine CPU/RAM/GPU/NET/DISK/TEMP etc.
|
|
22
|
-
It is very easy to start and use.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## Features
|
|
98
|
+
#### Features
|
|
26
99
|
|
|
27
100
|
- **Experiment Tracking:** Easily log and track your machine learning experiments.
|
|
28
101
|
- **Experiment Comparison:** Compare different experiments and their results.
|
|
@@ -30,6 +103,7 @@ It is very easy to start and use.
|
|
|
30
103
|
- **Integration with sciveo.com:** Seamlessly connect and synchronize with the sciveo.com platform.
|
|
31
104
|
- **Monitoring machines (from HPC to jetson nano):** Visualisation and metrics collection in sciveo platform.
|
|
32
105
|
|
|
106
|
+
|
|
33
107
|
## Installation
|
|
34
108
|
|
|
35
109
|
- main sciveo
|
|
@@ -39,10 +113,15 @@ pip install sciveo
|
|
|
39
113
|
pip install sciveo[mon]
|
|
40
114
|
- optional for sciveo network tools
|
|
41
115
|
pip install sciveo[net]
|
|
42
|
-
|
|
43
|
-
- for full installation
|
|
116
|
+
- for full installation, without media and ML support
|
|
44
117
|
pip install sciveo[all]
|
|
45
118
|
|
|
119
|
+
- for media (images/video/audio/text)
|
|
120
|
+
pip install sciveo[media]
|
|
121
|
+
- for media with ML processors
|
|
122
|
+
pip install sciveo[media-ml]
|
|
123
|
+
|
|
124
|
+
|
|
46
125
|
## Example usage
|
|
47
126
|
|
|
48
127
|
There are few public examples in sciveo.com.
|
|
@@ -78,11 +157,6 @@ sciveo.monitor(period=120, block=False)
|
|
|
78
157
|
|
|
79
158
|
```
|
|
80
159
|
|
|
81
|
-
Sciveo Scan hosts port tool available
|
|
82
|
-
```shell
|
|
83
|
-
sciveo scan --port 22 --timeout 0.5
|
|
84
|
-
```
|
|
85
|
-
|
|
86
160
|
|
|
87
161
|
Experimental Projects management
|
|
88
162
|
|
|
@@ -1,16 +1,89 @@
|
|
|
1
1
|
# SCIVEO - ML/AI and Scientific tools
|
|
2
2
|
|
|
3
|
+
## Monitoring ML Infrastructure
|
|
4
|
+
sciveo monitoring of (ML) machines' CPU/RAM/GPU/NET/DISK/TEMP etc.
|
|
5
|
+
It is very easy to start and use with a single command line.
|
|
6
|
+
|
|
7
|
+
- **Monitoring** of current machine with sampling period of 60 seconds
|
|
8
|
+
```shell
|
|
9
|
+
sciveo monitor --period 60
|
|
10
|
+
```
|
|
11
|
+
- **Monitoring** of current machine, logging the samples to local file (in this case the ./sciveo_monitor.json default name when dir path is used)
|
|
12
|
+
```shell
|
|
13
|
+
sciveo monitor --period 120 --output-path ./
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The monitor client is sendind the monitored samples to remote [sciveo](https://sciveo.com) api (init config located in ~/.sciveo/)
|
|
17
|
+
|
|
18
|
+
### Watchdog monitoring with action
|
|
19
|
+
- **Memory usage** watchdog for 90% max memory, measure every 10 seconds and execute "<some command to handle the high memory event>"
|
|
20
|
+
```shell
|
|
21
|
+
sciveo watchdog --src memory --threshold 90 --period 10 --execute "<some command to handle the high memory event>"
|
|
22
|
+
```
|
|
23
|
+
- **Disk usage** watchdog for 80% max disk usage on /some/path/to/watch path, measure every 600 seconds and execute "<some command to handle the high disk usage event>".
|
|
24
|
+
```shell
|
|
25
|
+
sciveo watchdog --src disk --input-path "/some/path/to/watch" --threshold 80 --period 600 --execute "find /some/path/to/watch -type f -mtime +1"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Network tools
|
|
30
|
+
|
|
31
|
+
- **Network Scan** Networks of hosts to scan for a single port
|
|
32
|
+
```shell
|
|
33
|
+
sciveo scan --port 22
|
|
34
|
+
|
|
35
|
+
sciveo scan --net 192.168.0.0/24 --port 22 --timeout 0.5
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- **Network Scan** Single Host list of ports to scan
|
|
39
|
+
```shell
|
|
40
|
+
sciveo scan --host 192.168.0.10
|
|
41
|
+
|
|
42
|
+
sciveo scan --host 192.168.0.10 --ports [443,80]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Remote network video recorder
|
|
46
|
+
|
|
47
|
+
- **NVR** RTSP cams video recorder
|
|
48
|
+
```shell
|
|
49
|
+
sciveo nvr --input-path cams.json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
where cams.json has the cam and nvr configuration like
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"video_retention_period": 5,
|
|
56
|
+
"max_video_len": 60,
|
|
57
|
+
"transport": "tcp",
|
|
58
|
+
"path": {
|
|
59
|
+
"tmp": "tmp/nvr/tmp",
|
|
60
|
+
"video": "tmp/nvr/video"
|
|
61
|
+
},
|
|
62
|
+
"cam": {
|
|
63
|
+
"cam_livingroom": {
|
|
64
|
+
"url": "rtsp://192.168.1.11/stream1"
|
|
65
|
+
},
|
|
66
|
+
"cam_kitchen": {
|
|
67
|
+
"url": "rtsp://rtsp://192.168.1.12"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## Media pipelines processing worker
|
|
75
|
+
- **Media Pipelines processing** service
|
|
76
|
+
```shell
|
|
77
|
+
sciveo media-server
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
|
|
3
81
|
## Experiments Management Client
|
|
4
82
|
`sciveo` is a Python library that serves as a client for managing machine learning and scientific experiments on the sciveo.com platform. This library provides a convenient interface to interact with the sciveo.com API, enabling users to organize, track, and analyze their experiments efficiently.
|
|
5
83
|
There are few configuration params samplers, which allows easy parameter tuning. The "auto" sampler perhaps is the easiest to use, but also
|
|
6
84
|
"random" and "grid" ones are available.
|
|
7
85
|
|
|
8
|
-
|
|
9
|
-
There is also the sciveo.monitor() which will start monitoring machine CPU/RAM/GPU/NET/DISK/TEMP etc.
|
|
10
|
-
It is very easy to start and use.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Features
|
|
86
|
+
#### Features
|
|
14
87
|
|
|
15
88
|
- **Experiment Tracking:** Easily log and track your machine learning experiments.
|
|
16
89
|
- **Experiment Comparison:** Compare different experiments and their results.
|
|
@@ -18,6 +91,7 @@ It is very easy to start and use.
|
|
|
18
91
|
- **Integration with sciveo.com:** Seamlessly connect and synchronize with the sciveo.com platform.
|
|
19
92
|
- **Monitoring machines (from HPC to jetson nano):** Visualisation and metrics collection in sciveo platform.
|
|
20
93
|
|
|
94
|
+
|
|
21
95
|
## Installation
|
|
22
96
|
|
|
23
97
|
- main sciveo
|
|
@@ -27,10 +101,15 @@ pip install sciveo
|
|
|
27
101
|
pip install sciveo[mon]
|
|
28
102
|
- optional for sciveo network tools
|
|
29
103
|
pip install sciveo[net]
|
|
30
|
-
|
|
31
|
-
- for full installation
|
|
104
|
+
- for full installation, without media and ML support
|
|
32
105
|
pip install sciveo[all]
|
|
33
106
|
|
|
107
|
+
- for media (images/video/audio/text)
|
|
108
|
+
pip install sciveo[media]
|
|
109
|
+
- for media with ML processors
|
|
110
|
+
pip install sciveo[media-ml]
|
|
111
|
+
|
|
112
|
+
|
|
34
113
|
## Example usage
|
|
35
114
|
|
|
36
115
|
There are few public examples in sciveo.com.
|
|
@@ -66,11 +145,6 @@ sciveo.monitor(period=120, block=False)
|
|
|
66
145
|
|
|
67
146
|
```
|
|
68
147
|
|
|
69
|
-
Sciveo Scan hosts port tool available
|
|
70
|
-
```shell
|
|
71
|
-
sciveo scan --port 22 --timeout 0.5
|
|
72
|
-
```
|
|
73
|
-
|
|
74
148
|
|
|
75
149
|
Experimental Projects management
|
|
76
150
|
|
|
@@ -15,6 +15,7 @@ import time
|
|
|
15
15
|
import json
|
|
16
16
|
import argparse
|
|
17
17
|
|
|
18
|
+
from sciveo.version import __version__
|
|
18
19
|
from sciveo.tools.logger import *
|
|
19
20
|
from sciveo.tools.configuration import GlobalConfiguration
|
|
20
21
|
|
|
@@ -22,7 +23,7 @@ from sciveo.tools.configuration import GlobalConfiguration
|
|
|
22
23
|
def main():
|
|
23
24
|
config = GlobalConfiguration.get()
|
|
24
25
|
|
|
25
|
-
parser = argparse.ArgumentParser(description='
|
|
26
|
+
parser = argparse.ArgumentParser(description=f'{config.name} CLI')
|
|
26
27
|
parser.add_argument(
|
|
27
28
|
'command',
|
|
28
29
|
choices=[
|
|
@@ -66,13 +67,14 @@ def main():
|
|
|
66
67
|
else:
|
|
67
68
|
NetworkTools(timeout=args.timeout, ports=json.loads(args.ports)).scan_host(host)
|
|
68
69
|
elif args.command == 'init':
|
|
70
|
+
info(f"init {config.name} ver {__version__}")
|
|
69
71
|
home = os.path.expanduser('~')
|
|
70
|
-
base_path = os.path.join(home, '.
|
|
72
|
+
base_path = os.path.join(home, f'.{config.name}')
|
|
71
73
|
if not os.path.exists(base_path):
|
|
72
74
|
os.makedirs(base_path)
|
|
73
75
|
default_lines = [
|
|
74
76
|
"secret_access_key=<your secret access key>",
|
|
75
|
-
"api_base_url=https://
|
|
77
|
+
f"api_base_url=https://{config.name}.com",
|
|
76
78
|
"sci_log_level=DEBUG"
|
|
77
79
|
]
|
|
78
80
|
with open(os.path.join(base_path, "default"), 'w') as fp:
|
|
@@ -81,7 +83,7 @@ def main():
|
|
|
81
83
|
else:
|
|
82
84
|
info(f"init, [{base_path}] already there")
|
|
83
85
|
elif args.command == 'nvr':
|
|
84
|
-
from sciveo.media.
|
|
86
|
+
from sciveo.media.capture.nvr import VideoRecorder
|
|
85
87
|
VideoRecorder(args.input_path).start()
|
|
86
88
|
elif args.command == 'media-server':
|
|
87
89
|
from sciveo.media.pipelines.server import __START_SCIVEO_MEDIA_SERVER__
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2024
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
import time
|
|
13
|
+
import numpy as np
|
|
14
|
+
import cv2
|
|
15
|
+
import base64
|
|
16
|
+
import threading
|
|
17
|
+
import mss
|
|
18
|
+
|
|
19
|
+
from sciveo.tools.logger import *
|
|
20
|
+
from sciveo.tools.daemon import DaemonBase
|
|
21
|
+
from sciveo.tools.timers import FPSCounter
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CaptureBase(DaemonBase):
|
|
25
|
+
def __init__(self, src, tag="capture", period=0):
|
|
26
|
+
super().__init__(period=period)
|
|
27
|
+
self.src = src
|
|
28
|
+
self.tag = tag
|
|
29
|
+
self.lock_frame = threading.Lock()
|
|
30
|
+
self.frame = None
|
|
31
|
+
self.fps = FPSCounter(period=10, tag=f"{self.tag} [{self.src}]")
|
|
32
|
+
|
|
33
|
+
def close(self):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
def read(self):
|
|
37
|
+
with self.lock_frame:
|
|
38
|
+
return self.frame
|
|
39
|
+
|
|
40
|
+
def read_buf(self):
|
|
41
|
+
frame = self.read()
|
|
42
|
+
ret, buffer = cv2.imencode('.jpg', frame)
|
|
43
|
+
return buffer.tobytes()
|
|
44
|
+
|
|
45
|
+
def read_frame(self):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def loop(self):
|
|
49
|
+
with self.lock_frame:
|
|
50
|
+
self.read_frame()
|
|
51
|
+
self.fps.update()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CameraDaemon(CaptureBase):
|
|
55
|
+
def __init__(self, cam_id=0, period=0):
|
|
56
|
+
super().__init__(src=cam_id, tag="cam", period=period)
|
|
57
|
+
self.cap = cv2.VideoCapture(cam_id)
|
|
58
|
+
debug(cam_id, "warming...")
|
|
59
|
+
time.sleep(1)
|
|
60
|
+
|
|
61
|
+
def close(self):
|
|
62
|
+
self.cap.release()
|
|
63
|
+
|
|
64
|
+
def read_frame(self):
|
|
65
|
+
ret, self.frame = self.cap.read()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class PredictorCameraDaemon(DaemonBase):
|
|
69
|
+
def __init__(self, args, cam, client):
|
|
70
|
+
super().__init__()
|
|
71
|
+
self.args = args
|
|
72
|
+
self.client = client
|
|
73
|
+
self.cam = cam
|
|
74
|
+
self.frame = None
|
|
75
|
+
self.fps = FPSCounter(period=10, tag="predictor")
|
|
76
|
+
self.lock_frame = threading.Lock()
|
|
77
|
+
|
|
78
|
+
def loop(self):
|
|
79
|
+
frame = self.cam.read()
|
|
80
|
+
image_base64 = self.client.image_encoded(image=frame)
|
|
81
|
+
|
|
82
|
+
if self.args.input_type == 0:
|
|
83
|
+
params = {
|
|
84
|
+
"predictor": self.args.predictor,
|
|
85
|
+
"compressed": self.args.compressed,
|
|
86
|
+
"X": [{
|
|
87
|
+
"messages": [{
|
|
88
|
+
"role": "user",
|
|
89
|
+
"content": [
|
|
90
|
+
{"type": "image"},
|
|
91
|
+
{"type": "text", "text": self.args.prompt},
|
|
92
|
+
]
|
|
93
|
+
}],
|
|
94
|
+
"images": [image_base64]
|
|
95
|
+
}]
|
|
96
|
+
}
|
|
97
|
+
elif self.args.input_type == 1:
|
|
98
|
+
params = {
|
|
99
|
+
"predictor": self.args.predictor,
|
|
100
|
+
"compressed": self.args.compressed,
|
|
101
|
+
"X": [image_base64]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
r = self.client.predict(params)
|
|
105
|
+
prediction = r[self.args.predictor][0]
|
|
106
|
+
info(prediction)
|
|
107
|
+
self.fps.update()
|
|
108
|
+
|
|
109
|
+
if isinstance(prediction, list) == False and isinstance(prediction, dict) == False:
|
|
110
|
+
cv2.putText(frame, prediction, (10, 100),
|
|
111
|
+
fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1.3, color=(255, 255, 255), thickness=3
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
with self.lock_frame:
|
|
115
|
+
self.frame = frame
|
|
116
|
+
|
|
117
|
+
def read(self):
|
|
118
|
+
with self.lock_frame:
|
|
119
|
+
return self.frame
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class ScreenDaemon(CaptureBase):
|
|
123
|
+
def __init__(self, src=1, period=0, region=None):
|
|
124
|
+
super().__init__(src=src, tag="screen", period=period)
|
|
125
|
+
self.sct = mss.mss()
|
|
126
|
+
self.monitor = self.sct.monitors[src]
|
|
127
|
+
|
|
128
|
+
if region:
|
|
129
|
+
self.monitor = {
|
|
130
|
+
"left": region[0],
|
|
131
|
+
"top": region[1],
|
|
132
|
+
"width": region[2],
|
|
133
|
+
"height": region[3],
|
|
134
|
+
}
|
|
135
|
+
debug(f"Capturing screen region: {self.monitor}")
|
|
136
|
+
else:
|
|
137
|
+
self.monitor = self.sct.monitors[src]
|
|
138
|
+
debug(f"Capturing full monitor {src}: {self.monitor}")
|
|
139
|
+
|
|
140
|
+
def close(self):
|
|
141
|
+
self.sct.close()
|
|
142
|
+
|
|
143
|
+
def read_frame(self):
|
|
144
|
+
sct_img = self.sct.grab(self.monitor)
|
|
145
|
+
self.frame = np.array(sct_img)
|
|
146
|
+
self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGRA2BGR)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == '__main__':
|
|
150
|
+
cap = ScreenDaemon(src=1, region=[300,300, 800,800])
|
|
151
|
+
cap.start()
|
|
152
|
+
while(True):
|
|
153
|
+
frame = cap.read()
|
|
154
|
+
frame = cv2.resize(frame, (250, 250))
|
|
155
|
+
cv2.imshow("captured", frame)
|
|
156
|
+
cv2.waitKey(1)
|
|
@@ -23,7 +23,7 @@ class BaseInteractiveVideoPlayer:
|
|
|
23
23
|
def __init__(self, path_video, tag):
|
|
24
24
|
self.path_video = path_video
|
|
25
25
|
self.file_name = os.path.basename(self.path_video)
|
|
26
|
-
self.file_name_base =
|
|
26
|
+
self.file_name_base = os.path.splitext(self.file_name)[0]
|
|
27
27
|
self.path_base = os.path.dirname(self.path_video)
|
|
28
28
|
self.tag = tag
|
|
29
29
|
self.frame_tag = f"Video {tag}"
|
|
@@ -89,7 +89,10 @@ class ImageEmbedding(BaseImageML):
|
|
|
89
89
|
def predict_one(self, x):
|
|
90
90
|
self.init()
|
|
91
91
|
image = self.read_image(x)
|
|
92
|
-
|
|
92
|
+
embedding = self.embed(image)
|
|
93
|
+
if not isinstance(embedding, list):
|
|
94
|
+
embedding = embedding.tolist()
|
|
95
|
+
return embedding
|
|
93
96
|
|
|
94
97
|
def predict(self, X):
|
|
95
98
|
self.init()
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2025
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import time
|
|
14
|
+
import cv2
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
from sciveo.tools.logger import *
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MapContoursUI:
|
|
21
|
+
def __init__(self, image_path):
|
|
22
|
+
self.image_path = image_path
|
|
23
|
+
self.image = cv2.imread(image_path)
|
|
24
|
+
if self.image is None:
|
|
25
|
+
raise ValueError(f"Image not found: {image_path}")
|
|
26
|
+
self.contours = []
|
|
27
|
+
self.current_contour = []
|
|
28
|
+
self.current_mouse_pos = (0, 0)
|
|
29
|
+
self.drawing = False
|
|
30
|
+
self.display = self.image.copy()
|
|
31
|
+
|
|
32
|
+
def _mouse_callback(self, event, x, y, flags, param):
|
|
33
|
+
if event == cv2.EVENT_MOUSEMOVE:
|
|
34
|
+
self.current_mouse_pos = (x, y)
|
|
35
|
+
|
|
36
|
+
def draw(self):
|
|
37
|
+
cv2.namedWindow("Contour Drawing")
|
|
38
|
+
cv2.setMouseCallback("Contour Drawing", self._mouse_callback)
|
|
39
|
+
|
|
40
|
+
print("\nControls:\n"
|
|
41
|
+
" c - Start new contour\n"
|
|
42
|
+
" v - Add point\n"
|
|
43
|
+
" x - Finalize contour\n"
|
|
44
|
+
" u - Undo last contour\n"
|
|
45
|
+
" z - Finish & show areas\n")
|
|
46
|
+
|
|
47
|
+
while True:
|
|
48
|
+
frame = self.display.copy()
|
|
49
|
+
|
|
50
|
+
for cnt in self.contours:
|
|
51
|
+
cv2.polylines(frame, [cnt], isClosed=True, color=(255, 0, 255), thickness=2)
|
|
52
|
+
|
|
53
|
+
if self.current_contour:
|
|
54
|
+
pts = self.current_contour + [self.current_mouse_pos]
|
|
55
|
+
for i in range(1, len(pts)):
|
|
56
|
+
cv2.line(frame, pts[i - 1], pts[i], (0, 255, 255), 1)
|
|
57
|
+
|
|
58
|
+
cv2.circle(frame, self.current_mouse_pos, 5, (0, 255, 0), -1)
|
|
59
|
+
|
|
60
|
+
self.draw_contour_indexes(frame)
|
|
61
|
+
self.draw_contour_lengths(frame)
|
|
62
|
+
|
|
63
|
+
cv2.imshow("Contour Drawing", frame)
|
|
64
|
+
key = cv2.waitKey(1) & 0xFF
|
|
65
|
+
|
|
66
|
+
if key == ord('c'): # Start new contour
|
|
67
|
+
self.current_contour = []
|
|
68
|
+
self.drawing = True
|
|
69
|
+
print("Started new contour.")
|
|
70
|
+
|
|
71
|
+
elif key == ord('v') and self.drawing: # Add point
|
|
72
|
+
self.current_contour.append(self.current_mouse_pos)
|
|
73
|
+
print(f"Added point: {self.current_mouse_pos}")
|
|
74
|
+
|
|
75
|
+
elif key == ord('x') and self.drawing: # Finalize
|
|
76
|
+
if len(self.current_contour) >= 3:
|
|
77
|
+
self.contours.append(np.array(self.current_contour, dtype=np.int32))
|
|
78
|
+
print("Contour finalized.")
|
|
79
|
+
else:
|
|
80
|
+
print("Contour discarded (not enough points).")
|
|
81
|
+
self.current_contour = []
|
|
82
|
+
self.drawing = False
|
|
83
|
+
|
|
84
|
+
elif key == ord('u') and self.contours: # Undo
|
|
85
|
+
self.contours.pop()
|
|
86
|
+
print("Last contour removed.")
|
|
87
|
+
|
|
88
|
+
elif key == ord('z'): # Finish
|
|
89
|
+
cv2.destroyWindow("Contour Drawing")
|
|
90
|
+
break
|
|
91
|
+
|
|
92
|
+
self.print_area_summary()
|
|
93
|
+
time.sleep(5)
|
|
94
|
+
cv2.destroyAllWindows()
|
|
95
|
+
|
|
96
|
+
def draw_contour_indexes(self, frame):
|
|
97
|
+
for idx, cnt in enumerate(self.contours):
|
|
98
|
+
M = cv2.moments(cnt)
|
|
99
|
+
if M["m00"] != 0:
|
|
100
|
+
cx = int(M["m10"] / M["m00"])
|
|
101
|
+
cy = int(M["m01"] / M["m00"])
|
|
102
|
+
cv2.putText(frame, str(idx + 1), (cx - 10, cy + 10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3)
|
|
103
|
+
|
|
104
|
+
def draw_contour_lengths(self, frame):
|
|
105
|
+
for cnt in self.contours:
|
|
106
|
+
points = cnt.reshape(-1, 2)
|
|
107
|
+
for i in range(len(points)):
|
|
108
|
+
p1 = points[i]
|
|
109
|
+
p2 = points[(i + 1) % len(points)]
|
|
110
|
+
dist = int(np.linalg.norm(p1 - p2))
|
|
111
|
+
mid = ((p1[0] + p2[0]) // 2, (p1[1] + p2[1]) // 2)
|
|
112
|
+
cv2.putText(frame, f"{dist}px", mid, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1)
|
|
113
|
+
|
|
114
|
+
if self.current_contour:
|
|
115
|
+
pts = self.current_contour + [self.current_mouse_pos]
|
|
116
|
+
for i in range(len(pts) - 1):
|
|
117
|
+
cv2.line(frame, pts[i], pts[i + 1], (0, 255, 0), 1)
|
|
118
|
+
|
|
119
|
+
dist = int(np.linalg.norm(np.array(pts[i]) - np.array(pts[i + 1])))
|
|
120
|
+
mid = ((pts[i][0] + pts[i + 1][0]) // 2, (pts[i][1] + pts[i + 1][1]) // 2)
|
|
121
|
+
cv2.putText(frame, f"{dist}px", mid, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
|
|
122
|
+
|
|
123
|
+
def print_area_summary(self):
|
|
124
|
+
info("🧮 Contour Areas")
|
|
125
|
+
for i, cnt in enumerate(self.contours):
|
|
126
|
+
area = cv2.contourArea(cnt)
|
|
127
|
+
info(f"Contour {i+1}: Area = {area:.2f}")
|
|
128
|
+
|
|
129
|
+
def save(self, path):
|
|
130
|
+
np.save(path, np.array(self.contours, dtype=object))
|
|
131
|
+
info(f"Contours saved to: {path}")
|
|
132
|
+
|
|
133
|
+
def load(self, path):
|
|
134
|
+
if os.path.exists(path):
|
|
135
|
+
loaded = np.load(path, allow_pickle=True)
|
|
136
|
+
self.contours = list(loaded)
|
|
137
|
+
info(f"Contours loaded from: {path}")
|
|
138
|
+
self.print_area_summary()
|
|
139
|
+
else:
|
|
140
|
+
info(f"File not found: {path}")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
ui = MapContoursUI(os.environ["PATH_IMAGE"])
|
|
145
|
+
ui.load(os.environ["PATH_SAVE_CONTOURS"])
|
|
146
|
+
ui.draw()
|
|
147
|
+
ui.save(os.environ["PATH_SAVE_CONTOURS"])
|