Compare commits
46 Commits
experiment
...
826e545652
| Author | SHA1 | Date | |
|---|---|---|---|
| 826e545652 | |||
| d30a55fb0b | |||
| d703f9cd9f | |||
| ad2d136e3f | |||
| 6354bd01e2 | |||
| 9d1ac9c3dd | |||
| 61c8f8bd90 | |||
|
|
3a420c7bbb | ||
|
|
a24e2d5cdc | ||
|
|
bce8cdaec6 | ||
|
|
24cb9b214c | ||
|
|
f2b37b8129 | ||
|
|
cc4acb3d3d | ||
|
|
1de630149d | ||
|
|
d57bd9f00f | ||
|
|
223b559869 | ||
|
|
40ad3143b5 | ||
|
|
acf50c199c | ||
|
|
dffeb995a0 | ||
|
|
003ea7ddcf | ||
|
|
9f5c3f014c | ||
|
|
562e2958b1 | ||
|
|
bd7c32cb52 | ||
|
|
633af882ca | ||
|
|
d2864fd337 | ||
|
|
08431ee6ca | ||
|
|
7dcf03970e | ||
|
|
44f2797a5c | ||
|
|
98ad6242fa | ||
|
|
b3b3d77394 | ||
|
|
e50ab9d03c | ||
|
|
c9c60f7237 | ||
|
|
de156a5c33 | ||
|
|
e4ec7fe244 | ||
|
|
1546528550 | ||
|
|
e7b4cc0f92 | ||
|
|
199d81891f | ||
|
|
ea1f0bcd85 | ||
|
|
9ae940585a | ||
|
|
78403395c1 | ||
|
|
b313fc7629 | ||
|
|
3c847cee01 | ||
|
|
9ed0b768b8 | ||
|
|
4a06b759e3 | ||
|
|
2887e2927c | ||
| 6da4cd2b40 |
43
.gitea/workflows/run-mucapy.yml
Normal file
43
.gitea/workflows/run-mucapy.yml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Build MuCaPy Executable
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-package:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
- name: Install PyInstaller
|
||||||
|
run: pip install pyinstaller
|
||||||
|
|
||||||
|
- name: Build executable with PyInstaller
|
||||||
|
run: |
|
||||||
|
pyinstaller --onefile --windowed mucapy/main.py \
|
||||||
|
--add-data "mucapy/styling:styling" \
|
||||||
|
--add-data "mucapy/models:models" \
|
||||||
|
--add-data "mucapy/todopackage:todopackage"
|
||||||
|
|
||||||
|
- name: Upload executable artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mucapy-executable
|
||||||
|
path: dist/
|
||||||
|
|
||||||
|
|
||||||
103
.gitignore
vendored
103
.gitignore
vendored
@@ -1 +1,104 @@
|
|||||||
|
|
||||||
|
# ============================
|
||||||
|
# IDEs and Editors
|
||||||
|
# ============================
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# Python
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
ENV/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
pip-log.txt
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# Logs / runtime / temp files
|
||||||
|
# ============================
|
||||||
|
*.log
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.out
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
*.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# System and OS junk
|
||||||
|
# ============================
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
.DS_Store
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# Custom project folders
|
||||||
|
# ============================
|
||||||
|
# Ignore project-specific compiled caches or outputs
|
||||||
|
mucapy/**/__pycache__/
|
||||||
|
|||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
13
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
13
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredErrors">
|
||||||
|
<list>
|
||||||
|
<option value="N812" />
|
||||||
|
<option value="N802" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
12
.idea/material_theme_project_new.xml
generated
Normal file
12
.idea/material_theme_project_new.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MaterialThemeProjectNewConfig">
|
||||||
|
<option name="metadata">
|
||||||
|
<MTProjectMetadataState>
|
||||||
|
<option name="migrated" value="true" />
|
||||||
|
<option name="pristineConfig" value="false" />
|
||||||
|
<option name="userId" value="13ba7435:19917931603:-7ffa" />
|
||||||
|
</MTProjectMetadataState>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.13 (mucapy)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (mucapy)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/mucapy.iml" filepath="$PROJECT_DIR$/.idea/mucapy.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
14
.idea/mucapy.iml
generated
Normal file
14
.idea/mucapy.iml
generated
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.13 (mucapy)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="PyDocumentationSettings">
|
||||||
|
<option name="format" value="PLAIN" />
|
||||||
|
<option name="myDocStringFormat" value="Plain" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
41
LICENSE
Normal file
41
LICENSE
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
MuCaPy Proprietary Software License
|
||||||
|
Version 1.0 — May 30, 2025
|
||||||
|
|
||||||
|
Copyright © 2025 Rattatwinko
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
This software, including all source code, binaries, documentation, and associated files (collectively, the "Software"), is the exclusive property of the copyright holder.
|
||||||
|
|
||||||
|
The Software is proprietary and confidential. It is licensed, not sold, solely for internal, non-commercial use by the copyright holder or explicitly authorized individuals.
|
||||||
|
1. License Grant
|
||||||
|
|
||||||
|
The copyright holder does not grant any rights to use, copy, modify, distribute, sublicense, or create derivative works from the Software except as explicitly authorized in writing.
|
||||||
|
2. Restrictions
|
||||||
|
|
||||||
|
You shall not, under any circumstances:
|
||||||
|
|
||||||
|
Redistribute the Software in any form (source or binary).
|
||||||
|
|
||||||
|
Publish, transmit, upload, or make the Software publicly available.
|
||||||
|
|
||||||
|
Reverse engineer, decompile, or disassemble the Software.
|
||||||
|
|
||||||
|
Use the Software for any commercial or revenue-generating purpose.
|
||||||
|
|
||||||
|
Share the Software with third parties, contractors, or external collaborators.
|
||||||
|
|
||||||
|
Access to the Software must remain confined to private, secure environments under the control of the copyright holder.
|
||||||
|
3. Ownership
|
||||||
|
|
||||||
|
All title, ownership rights, and intellectual property rights in and to the Software remain solely with the copyright holder.
|
||||||
|
4. Termination
|
||||||
|
|
||||||
|
Any unauthorized use of the Software automatically terminates any implied rights and may result in legal action.
|
||||||
|
5. Disclaimer of Warranty
|
||||||
|
|
||||||
|
The Software is provided "AS IS" without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, or non-infringement.
|
||||||
|
6. Limitation of Liability
|
||||||
|
|
||||||
|
In no event shall the copyright holder be liable for any damages, including direct, indirect, incidental, special, or consequential damages arising out of or related to the use or inability to use the Software.
|
||||||
|
|
||||||
|
This license is not OSI-approved and must not be interpreted as open-source. For internal use only.
|
||||||
166
README.md
Normal file
166
README.md
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
# MuCaPy: Multi-Camera Python🎥🧠
|
||||||
|
|
||||||
|
[](https://www.python.org/)
|
||||||
|
[]()
|
||||||
|
[](https://opencv.org/)
|
||||||
|
[](https://riverbankcomputing.com/software/pyqt/)
|
||||||
|
[]()
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📌 Overview
|
||||||
|
|
||||||
|
**MuCaPy** (Multi-Camera Python) is a modern, robust, and user-friendly real-time multi-camera object detection platform powered by **YOLOv4** and **OpenCV**, designed with a professional PyQt5 GUI. It supports both **local** and **network IP cameras**, allows dynamic camera selection, advanced configuration, and comes with a beautiful dark-themed UI. CUDA support ensures high performance where available.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
- 🔁 Connect multiple **local USB or IP cameras**
|
||||||
|
- 💡 Real-time **YOLOv4 object detection**
|
||||||
|
- 🎛️ Intelligent UI with **PyQt5**, collapsible dock widgets, and tabbed views
|
||||||
|
- 📸 Take **screenshots** per camera feed
|
||||||
|
- ⚙️ **Model loader** for dynamic YOLO weight/config/class sets
|
||||||
|
- 🔌 **Network camera support** with authentication
|
||||||
|
- 🖥️ **Hardware monitor** (CPU and per-core utilization via `psutil`)
|
||||||
|
- 🖼️ Fullscreen/popout camera views with zoom, pan, grid & timestamp overlays, snapshots, and shortcuts
|
||||||
|
- 💾 Persistent **configuration management**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Requirements
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Troubleshooting (Windows): If you see "ImportError: DLL load failed while importing QtCore",
|
||||||
|
- Uninstall conflicting Qt packages: `pip uninstall -y python-qt5 PySide2 PySide6`
|
||||||
|
- Reinstall PyQt5: `pip install --upgrade --force-reinstall PyQt5==5.15.11`
|
||||||
|
- Install Microsoft VC++ x64 runtime: https://aka.ms/vs/17/release/vc_redist.x64.exe
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>Dependencies:</strong></summary>
|
||||||
|
|
||||||
|
- Python 3.8+
|
||||||
|
- OpenCV (cv2)
|
||||||
|
- PyQt5
|
||||||
|
- NumPy
|
||||||
|
- Requests
|
||||||
|
- psutil
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Getting Started
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
> ✅ Make sure your YOLOv4 model directory contains `.weights`, `.cfg`, and `.names` files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Model Directory Structure
|
||||||
|
This is important! If you dont have the correct directory structure, the model loader won't work.
|
||||||
|
|
||||||
|
Models are Included in the Git Repository!
|
||||||
|
|
||||||
|
```bash
|
||||||
|
model/
|
||||||
|
├── yolov4.cfg
|
||||||
|
├── yolov4.weights
|
||||||
|
└── coco.names
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 UI Highlights
|
||||||
|
|
||||||
|
- **Model Loader**: Easily select model directory
|
||||||
|
- **Camera Selection**: Mix and match local/network sources
|
||||||
|
- **Layouts**: Switch between 1, 2, 3, 4, or grid layouts
|
||||||
|
- **FPS Control**: Adjustable frame rate
|
||||||
|
- **Dark Theme**: Developer-friendly aesthetic
|
||||||
|
- **Screenshot Button**: Save current camera frame
|
||||||
|
- **Hardware Stats**: Monitor CPU load in real-time
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gitea Worflow Download
|
||||||
|
You can actually download Gitea Workflow compiled code that will run on your local machine. But for this to work you need to enter one of the following commands in your terminal:
|
||||||
|
```sh
|
||||||
|
chmod a+x main # or the name of your compiled file
|
||||||
|
```
|
||||||
|
|
||||||
|
>Note: _This will only work on Linux! **( This is cause of the Gitea Runner (Which runs on Ubuntu!))** If you are on Windows you can compile it yourself with PyInstaller_
|
||||||
|
|
||||||
|
[](run.mp4)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 Recommended YOLOv4 Model Links
|
||||||
|
|
||||||
|
- [YOLOv4.cfg](https://github.com/AlexeyAB/darknet/blob/master/cfg/yolov4.cfg)
|
||||||
|
- [YOLOv4.weights](https://github.com/AlexeyAB/darknet/releases/download/yolov4/yolov4.weights)
|
||||||
|
- [COCO.names](https://github.com/pjreddie/darknet/blob/master/data/coco.names)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Network Camera Example
|
||||||
|
|
||||||
|
Supports URLs like:
|
||||||
|
- `http://192.168.1.101:8080/video`
|
||||||
|
- `http://username:password@ip:port/stream`
|
||||||
|
|
||||||
|
Authentication is optional and can be configured per-camera.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## ⚙️ Configuration & Persistence
|
||||||
|
|
||||||
|
This is also Very Important if you have multiple cameras or want to save / delete your settings. You can save your settings to a file and load them later.
|
||||||
|
|
||||||
|
Settings (last model, selected cameras, layout, FPS, etc.) are saved to:
|
||||||
|
|
||||||
|
- **Linux/macOS**: `~/.config/mucapy/config.json`
|
||||||
|
- **Windows**: `%APPDATA%\MuCaPy\config.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📸 Screenshot Storage
|
||||||
|
|
||||||
|
Default directory: `~/Pictures/MuCaPy` (can be changed from the UI)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 About
|
||||||
|
|
||||||
|
> _I built MuCaPy to learn about OpenCV, Python, and to have a simple, easy-to-use camera viewer for my Camera Server, since ContaCam doesn't work on my system (not well atleast!)._
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔮 To Be Added
|
||||||
|
|
||||||
|
- **YOLOv5 / YOLOv8 / YOLO-NAS support**
|
||||||
|
- **RTSP stream handling** _( Currently works but is fuzzy / crashes easily)_
|
||||||
|
- **Real-time performance dashboards**
|
||||||
|
- **WebSocket remote monitoring**
|
||||||
|
- **Not-so-laggy UI improvements**
|
||||||
|
- **Better CUDA implementation**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
This Project is currently under a Proprietary Licsence and shouldnt be distributed!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧑💻 Maintainers
|
||||||
|
|
||||||
|
- 👤 Rattatwinko
|
||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
2336
mucapy/main.py
2336
mucapy/main.py
File diff suppressed because it is too large
Load Diff
36
mucapy/styling/about.qss
Normal file
36
mucapy/styling/about.qss
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
QDialog {
|
||||||
|
background-color: #2D2D2D;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel {
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 4px;
|
||||||
|
background-color: #252525;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
left: 10px;
|
||||||
|
padding: 0 3px;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
color: #DDD;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px;
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #4A4A4A;
|
||||||
|
}
|
||||||
11
mucapy/styling/bar/a85.qss
Normal file
11
mucapy/styling/bar/a85.qss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #E5A823;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
11
mucapy/styling/bar/else.qss
Normal file
11
mucapy/styling/bar/else.qss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #A23535;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
27
mucapy/styling/bar/seperate/a85.qss
Normal file
27
mucapy/styling/bar/seperate/a85.qss
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 2px solid #550000;
|
||||||
|
border-radius: 50px;
|
||||||
|
background-color: qradialgradient(
|
||||||
|
cx:0.5, cy:0.5,
|
||||||
|
fx:0.5, fy:0.5,
|
||||||
|
radius:1.0,
|
||||||
|
stop:0 #0d0d0d,
|
||||||
|
stop:1 #1a1a1a
|
||||||
|
);
|
||||||
|
text-align: center;
|
||||||
|
color: #cccccc;
|
||||||
|
font-family: "Fira Code", "OCR A Std", monospace;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background: qlineargradient(
|
||||||
|
x1:0, y1:0, x2:1, y2:1,
|
||||||
|
stop:0 #ff0033,
|
||||||
|
stop:1 #ff6666
|
||||||
|
);
|
||||||
|
border-radius: 50px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
27
mucapy/styling/bar/seperate/else.qss
Normal file
27
mucapy/styling/bar/seperate/else.qss
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 2px solid #550000;
|
||||||
|
border-radius: 50px;
|
||||||
|
background-color: qradialgradient(
|
||||||
|
cx:0.5, cy:0.5,
|
||||||
|
fx:0.5, fy:0.5,
|
||||||
|
radius:1.0,
|
||||||
|
stop:0 #0d0d0d,
|
||||||
|
stop:1 #1a1a1a
|
||||||
|
);
|
||||||
|
text-align: center;
|
||||||
|
color: #cccccc;
|
||||||
|
font-family: "Fira Code", "OCR A Std", monospace;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background: qlineargradient(
|
||||||
|
x1:0, y1:0, x2:1, y2:1,
|
||||||
|
stop:0 #ff0033,
|
||||||
|
stop:1 #ff6666
|
||||||
|
);
|
||||||
|
border-radius: 50px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
27
mucapy/styling/bar/seperate/u60.qss
Normal file
27
mucapy/styling/bar/seperate/u60.qss
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 2px solid #550000;
|
||||||
|
border-radius: 50px;
|
||||||
|
background-color: qradialgradient(
|
||||||
|
cx:0.5, cy:0.5,
|
||||||
|
fx:0.5, fy:0.5,
|
||||||
|
radius:1.0,
|
||||||
|
stop:0 #0d0d0d,
|
||||||
|
stop:1 #1a1a1a
|
||||||
|
);
|
||||||
|
text-align: center;
|
||||||
|
color: #cccccc;
|
||||||
|
font-family: "Fira Code", "OCR A Std", monospace;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background: qlineargradient(
|
||||||
|
x1:0, y1:0, x2:1, y2:1,
|
||||||
|
stop:0 #ff0033,
|
||||||
|
stop:1 #ff6666
|
||||||
|
);
|
||||||
|
border-radius: 50px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
11
mucapy/styling/bar/u60.qss
Normal file
11
mucapy/styling/bar/u60.qss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #3A6EA5;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
6
mucapy/styling/camera_display.qss
Normal file
6
mucapy/styling/camera_display.qss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
QLabel {
|
||||||
|
background-color: #1E1E1E;
|
||||||
|
color: #DDD;
|
||||||
|
border: 2px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
6
mucapy/styling/cleardisplay.qss
Normal file
6
mucapy/styling/cleardisplay.qss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
QLabel {
|
||||||
|
background-color: #1E1E1E;
|
||||||
|
color: #DDD;
|
||||||
|
border: 2px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
12
mucapy/styling/core_bar.qss
Normal file
12
mucapy/styling/core_bar.qss
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
max-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #3A6EA5;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
11
mucapy/styling/cpu_progress.qss
Normal file
11
mucapy/styling/cpu_progress.qss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
QProgressBar {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 2px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #3A6EA5;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
BIN
mucapy/styling/logo.png
Normal file
BIN
mucapy/styling/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
158
mucapy/styling/mainwindow.qss
Normal file
158
mucapy/styling/mainwindow.qss
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
QMainWindow, QWidget {
|
||||||
|
background-color: #2D2D2D;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel {
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
color: #DDD;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #4A4A4A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox, QSpinBox {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
color: #DDD;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-top: 15px;
|
||||||
|
background-color: #252525;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
left: 10px;
|
||||||
|
padding: 0 3px;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar {
|
||||||
|
background-color: #252525;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar::item {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar::item:selected {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu {
|
||||||
|
background-color: #252525;
|
||||||
|
border: 1px solid #444;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::item:selected {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollArea {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDockWidget {
|
||||||
|
titlebar-close-icon: url(none);
|
||||||
|
titlebar-normal-icon: url(none);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDockWidget::title {
|
||||||
|
background: #252525;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar:vertical {
|
||||||
|
background: #1E1E1E; /* Scrollbar background */
|
||||||
|
width: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical {
|
||||||
|
background: #3A3A3A; /* Scroll handle */
|
||||||
|
min-height: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:hover {
|
||||||
|
background: #555555; /* Hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:pressed {
|
||||||
|
background: #6A6A6A; /* Active color */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:vertical,
|
||||||
|
QScrollBar::sub-line:vertical {
|
||||||
|
height: 0px; /* Hide arrows */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:vertical,
|
||||||
|
QScrollBar::sub-page:vertical {
|
||||||
|
background: none; /* No gap color */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== Horizontal Scrollbar ===== */
|
||||||
|
QScrollBar:horizontal {
|
||||||
|
background: #1E1E1E;
|
||||||
|
height: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal {
|
||||||
|
background: #3A3A3A;
|
||||||
|
min-width: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:hover {
|
||||||
|
background: #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:pressed {
|
||||||
|
background: #6A6A6A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:horizontal,
|
||||||
|
QScrollBar::sub-line:horizontal {
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:horizontal,
|
||||||
|
QScrollBar::sub-page:horizontal {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
95
mucapy/styling/mw.qss
Normal file
95
mucapy/styling/mw.qss
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
QMainWindow, QWidget {
|
||||||
|
background-color: #2D2D2D;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel {
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
color: #DDD;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #4A4A4A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: #2A2A2A;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox, QSpinBox {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
color: #DDD;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox {
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-top: 15px;
|
||||||
|
background-color: #252525;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
left: 10px;
|
||||||
|
padding: 0 3px;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar {
|
||||||
|
background-color: #252525;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar::item {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar::item:selected {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu {
|
||||||
|
background-color: #252525;
|
||||||
|
border: 1px solid #444;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::item:selected {
|
||||||
|
background-color: #3A3A3A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollArea {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDockWidget {
|
||||||
|
titlebar-close-icon: url(none);
|
||||||
|
titlebar-normal-icon: url(none);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDockWidget::title {
|
||||||
|
background: #252525;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
5
mucapy/styling/todostyle.qss
Normal file
5
mucapy/styling/todostyle.qss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
QLabel#todoLabel {
|
||||||
|
color:rgb(21, 255, 0);
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
6
mucapy/styling/togglebtnabout.qss
Normal file
6
mucapy/styling/togglebtnabout.qss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
QToolButton {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #DDD;
|
||||||
|
}
|
||||||
0
mucapy/todopackage/__init__.py
Normal file
0
mucapy/todopackage/__init__.py
Normal file
112
mucapy/todopackage/todo.py
Normal file
112
mucapy/todopackage/todo.py
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
"""
|
||||||
|
Here we have a simple fucking class to get the fuckass Todo thing
|
||||||
|
Probably will do none of them
|
||||||
|
anyways, if you have suggestions pr this shit
|
||||||
|
|
||||||
|
idk if you are smarter than me then actually do them.
|
||||||
|
|
||||||
|
<-----------------------------------------------------------------
|
||||||
|
I feel more like a Frontend Dev doing this shit.
|
||||||
|
If you are a Frontend Dev then fuck you. Fuckass React Devs.
|
||||||
|
----------------------------------------------------------------->
|
||||||
|
|
||||||
|
fuck you , if you can't read this then kys. This is designed to be very readable.
|
||||||
|
-Rattatwinko 8.jun.25 (20:25)
|
||||||
|
"""
|
||||||
|
|
||||||
|
class todo:
|
||||||
|
def __init__(self):
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
self.information : str = """
|
||||||
|
|
||||||
|
MuCaPy TODO List:
|
||||||
|
|
||||||
|
NOTE: If you want to run this in Visual Studio Codes built in Terminal you will get fucked in your tiny tight ass.
|
||||||
|
NOTE: If you ran this from the Workflow Package, you cant do shit. fuck you.
|
||||||
|
NOTE: If you compiled this yourself ; you are one Fucking Genious
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
Todo in About ; Seperate File (@todo.py)
|
||||||
|
|
||||||
|
|
||||||
|
""" # This will center!
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
"""
|
||||||
|
!## This was the Quessadilla Bug at earlier 75. With next commit delete that out of the todo Variable ##!
|
||||||
|
|
||||||
|
This has nothing to do with the About Window
|
||||||
|
It just happens to fit in here.
|
||||||
|
I really dont like my Strings in my logic. It throws me off.
|
||||||
|
I know it overcomplicates shit but Python is readable anyways.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.instructions_CaSeDi_QLabel : str = """
|
||||||
|
|
||||||
|
Camera Selection Guide:\n
|
||||||
|
• Local Cameras: Built-in and USB cameras
|
||||||
|
• Network Cameras: IP cameras, DroidCam, etc.
|
||||||
|
• Use checkboxes to select/deselect cameras
|
||||||
|
• Double-click a camera to test the connection
|
||||||
|
• Selected cameras will appear in the preview bellow
|
||||||
|
"""
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
self.todo : str="""
|
||||||
|
TODO:
|
||||||
|
[] - Fix Network Cameras from Crashing the Programm (This sometimes happens when only network cams are selected and it times out)
|
||||||
|
[/] - Make Seperate Styling (unlikely that this will happen)
|
||||||
|
- CPU seperate styling is available , set variable in QMainWindow
|
||||||
|
[] - RTSP Camera Streaming
|
||||||
|
|
||||||
|
""" # This will display lefty (look in about window class)
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
self.cameraURL : str = """
|
||||||
|
Cameras:
|
||||||
|
- http://pendelcam.kip.uni-heidelberg.de/mjpg/video.mjpg
|
||||||
|
""" # This will also display centered
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
self.beaver : str="""
|
||||||
|
___
|
||||||
|
.=" "=._.---.
|
||||||
|
."" c ' Y'`p
|
||||||
|
/ , `. w_/
|
||||||
|
jgs | '-. / /
|
||||||
|
_,..._| )_-\ \_=.\
|
||||||
|
`-....-'`--------)))`=-'"`'"
|
||||||
|
""" # The beaver isnt really angry anymore. Idk why, now hes chill
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
self.archived_todo : str = """
|
||||||
|
Archived Todo List:
|
||||||
|
[X] - Fix Quesadilla Bug. @todo.py:75 , This has nothing to do with the About Window, but the Network Camera Dialog in @main.py:1038/1049
|
||||||
|
- Fixed this. @todo.py now has a Singleton Initializer. Idk. "Brotha ew - Tsoding in May". Fuck you
|
||||||
|
[] - Make MJPEG more stable and efficient. (maybe use c++ for this or rust)
|
||||||
|
- Wont happen ; remove next commit, this is as efficient as it gets
|
||||||
|
"""
|
||||||
|
#------------------------------------------------------------------------------------------------------------------------------------------------#
|
||||||
|
"""
|
||||||
|
|
||||||
|
For a change we actually declare the Types.
|
||||||
|
I usually leave this to the Interpreter, it does it anyway
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Return the Todo String
|
||||||
|
def gettodo(self) -> str:
|
||||||
|
return self.todo
|
||||||
|
# Return the Information about the Programm
|
||||||
|
def getinfo(self) -> str:
|
||||||
|
return self.information
|
||||||
|
|
||||||
|
# Return the Camera URL Thing
|
||||||
|
def getcams(self) -> str:
|
||||||
|
return self.cameraURL
|
||||||
|
# Get Network Camera Instructions (in the setup dialog)
|
||||||
|
def get_instructions_CaSeDi_QLabel(self) -> str:
|
||||||
|
return self.instructions_CaSeDi_QLabel
|
||||||
|
# Get the fuckass beaver. very angwy :3
|
||||||
|
def get_beaver(self) -> str:
|
||||||
|
return self.beaver
|
||||||
|
# Get the Archive.
|
||||||
|
def getarchive(self) -> str:
|
||||||
|
return self.archived_todo
|
||||||
|
|
||||||
|
todo = todo()
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
opencv-python>=4.5.0
|
opencv-python==4.11.0.86
|
||||||
opencv-contrib-python>=4.5.0
|
numpy==2.2.6
|
||||||
numpy>=1.19.0
|
PyQt5==5.15.11
|
||||||
PyQt5>=5.15.0
|
requests==2.32.3
|
||||||
|
psutil==7.0.0
|
||||||
|
pytest==8.4.0
|
||||||
Reference in New Issue
Block a user