first commit - demo version w\o bbox

This commit is contained in:
Mason Huang 2025-03-06 18:13:47 +08:00
commit 75e5925046
115 changed files with 32888 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

166
README.md Normal file
View File

@ -0,0 +1,166 @@
<!-- main page
1. -> example (python code) -> 讀 folder 檔案 -> 選
-> 抓 camera -> -i image -m model
2. run code -->
<!-- config for python script 需要有以下的資料:
1. function name to display
2. script name
3. device availibility (considering if the script name doesn't consist dongle type)
4. model's name
5. input information (frames, images, voice etc.)
6. input parameters
7. output parameters -->
# Innovedus AI Playground
這個應用程式是一個 AI Playground用於通過相機鏡頭或使用者上傳圖片進行推論例如火災檢測。應用程式基於 Python、PyQt5、OpenCV 以及 Kneron SDKkp開發支援 Video 模式與 Image 模式。
---
## 目錄
- [安裝設定](#安裝設定)
- [專案架構](#專案架構)
- [功能概述](#功能概述)
## 安裝設定
- Install python 3.12 and kneron plus
``` shell
# This shell script only install Kneron plus
cd ./external/kneron_plus_{version}/package/{platform}/
pip install KneronPLUS-{version}-py3-none-any.whl
# if the above command doesn't work
pip install --force-reinstall KneronPLUS-{version}-py3-none-any.whl
```
- PyQT5 and other packages
``` shell
pip install PyQt5 opencv-python pyinstaller pyarmor
```
- test APP in local
``` shell
python main.py
```
## 專案架構
```
project/
|- main.py
|- src/
|- config.py
|- controllers/
|- device_controllers.py
|- model_controllers.py
|- views/
|- mainwindow.py # 主視窗邏輯
|- utils/
|- file_utils.py # 文件工具
|- image_utils.py # 圖像工具
|- services/
|- device_service.py # 設備服務
|- model_service.py # 模型服務
|- models/
|- uxui/
|- tests/
|- unit/
|- integration/
```
```
upload/
└── photos, videos, or mp3 files
utils/
└── plugins/
├── mode1/
│ ├── model1/
│ │ ├── script.py
│ │ ├── model_file(s)
│ │ └── config.json
│ └── model2/
│ ├── script.py
│ ├── model_file(s)
│ └── config.json
└── mode2/
├── model1/
│ ├── script.py
│ ├── model_file(s)
│ └── config.json
└── model2/
├── script.py
├── model_file(s)
└── config.json
└──firmware\
├── KLXXX/
│ ├── fw_scpu.bin
│ ├── fw_ncpu.bin
│ ├── VERSION
│ └── other files
├── KLXXX/
├── fw_scpu.bin
├── fw_ncpu.bin
├── VERSION
└── other files
└──config.json
└──REAMDE.md
```
## 功能概述
- **Video 模式**:啟動相機持續捕捉影像,並將每一幀以 NumPy 陣列格式傳入推論模組進行即時推論。
- **Image 模式**:使用者上傳圖片後,讀取圖片並將其以 NumPy 陣列格式放入推論佇列,僅進行一次推論。
---
## 輸入資料格式
### 相機影像
- **捕捉方式**:使用 OpenCV 從相機捕捉影像。
- **轉換流程**
1. 影像先以 QImage 格式傳回。
2. 透過 `qimage_to_numpy(qimage)` 函式轉換為 NumPy 陣列。
- **格式**NumPy 陣列,形狀為 `(height, width, 3)`,通道順序為 RGB888。
### 上傳圖片
- **讀取方式**:使用 OpenCV 的 `cv2.imread()` 讀取上傳的圖片。
- **格式**:產生的圖片也是一個 NumPy 陣列(通常是 BGR 格式),後續推論模組可進一步進行預處理轉換。
---
## 參數傳遞與設定
### input_params 的組成
主應用程式會組合一個 `input_params` 字典,並將該字典傳遞給推論模組。此字典中可能包含以下鍵值:
- `usb_port_id`:選取的 dongle 的 USB port ID。
- `fw_folder`:全域 Firmware 資料夾路徑FW_DIR
- `scpu_path``ncpu_path`:根據選取的 dongle 型號,組合出的 firmware 檔案路徑。
- `file_path`上傳圖片的完整路徑image/voice 模式下使用)。
- `model`:從工具配置中讀取的模型檔案名稱,經由路徑組合後形成完整的模型路徑。
**範例**
```python
{
"usb_port_id": 32,
"scpu_path": "C:\\...\\firmware\\KL520\\fw_scpu.bin",
"ncpu_path": "C:\\...\\firmware\\KL520\\fw_ncpu.bin",
"fw_folder": "C:\\...\\firmware",
"file_path": "C:\\...\\uploads\\fire5.jpeg",
"model": "src\\utils\\models\\fire_detection_520.nef"
}
```
## APP 打包
目前是使用 Pyinstaller 來進行打包的動作 可以根據以下的指令進行打包
#### 下方的add-data需要根據你要包入的資料設定最後一個則是需要把 kp 包進 exe 檔中,需要去 conda 的 env 資料夾中找對應的 kp\lib 資料夾
```shell
pyinstaller --onefile --windowed main.py --additional-hooks-dir=hooks --add-data "uxui;uxui" --add-data "src;src" --add-data "C:\Users\mason\miniconda3\envs\resnet\Lib\site-packages\kp\lib;kp\lib"
```
## APP資料加密
目前預計使用 [pyarmor](https://github.com/dashingsoft/pyarmor) 進行加密

2696
build/main/Analysis-00.toc Normal file

File diff suppressed because it is too large Load Diff

1035
build/main/EXE-00.toc Normal file

File diff suppressed because it is too large Load Diff

1013
build/main/PKG-00.toc Normal file

File diff suppressed because it is too large Load Diff

BIN
build/main/PYZ-00.pyz Normal file

Binary file not shown.

1433
build/main/PYZ-00.toc Normal file

File diff suppressed because it is too large Load Diff

BIN
build/main/base_library.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
build/main/main.pkg Normal file

Binary file not shown.

233
build/main/warn-main.txt Normal file
View File

@ -0,0 +1,233 @@
This file lists modules PyInstaller was not able to find. This does not
necessarily mean this module is required for running your program. Python and
Python 3rd-party packages include a lot of conditional or optional modules. For
example the module 'ntpath' only exists on Windows, whereas the module
'posixpath' only exists on Posix systems.
Types if import:
* top-level: imported at the top-level - look at these first
* conditional: imported within an if-statement
* delayed: imported within a function
* optional: imported within a try-except-statement
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
tracking down the missing module yourself. Thanks!
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), http.server (delayed, optional), netrc (delayed, conditional), getpass (delayed)
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional)
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
missing module named fcntl - imported by subprocess (optional)
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
missing module named posix - imported by os (conditional, optional), shutil (conditional), importlib._bootstrap_external (conditional), posixpath (optional)
missing module named resource - imported by posix (top-level)
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
missing module named _scproxy - imported by urllib.request (conditional)
missing module named termios - imported by tty (top-level), getpass (optional)
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named pyimod02_importers - imported by C:\Users\mason\miniconda3\envs\resnet\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
missing module named _dummy_thread - imported by numpy._core.arrayprint (optional)
missing module named 'numpy_distutils.cpuinfo' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named 'numpy_distutils.fcompiler' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named 'numpy_distutils.command' - imported by numpy.f2py.diagnose (delayed, conditional, optional)
missing module named numpy_distutils - imported by numpy.f2py.diagnose (delayed, optional)
missing module named vms_lib - imported by platform (delayed, optional)
missing module named 'java.lang' - imported by platform (delayed, optional)
missing module named java - imported by platform (delayed)
missing module named _winreg - imported by platform (delayed, optional)
missing module named psutil - imported by numpy.testing._private.utils (delayed, optional)
missing module named win32evtlog - imported by logging.handlers (delayed, optional)
missing module named win32evtlogutil - imported by logging.handlers (delayed, optional)
missing module named startup - imported by pyreadline3.keysyms.common (conditional), pyreadline3.keysyms.keysyms (conditional)
missing module named sets - imported by pyreadline3.keysyms.common (optional)
missing module named System - imported by pyreadline3.clipboard.ironpython_clipboard (top-level), pyreadline3.keysyms.ironpython_keysyms (top-level), pyreadline3.console.ironpython_console (top-level), pyreadline3.rlmain (conditional)
missing module named console - imported by pyreadline3.console.ansi (conditional)
missing module named clr - imported by pyreadline3.clipboard.ironpython_clipboard (top-level), pyreadline3.console.ironpython_console (top-level)
missing module named IronPythonConsole - imported by pyreadline3.console.ironpython_console (top-level)
missing module named win32pdh - imported by numpy.testing._private.utils (delayed, conditional)
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
missing module named pyodide_js - imported by threadpoolctl (delayed, optional)
missing module named numpy._core.zeros - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.vstack - imported by numpy._core (top-level), numpy.lib._shape_base_impl (top-level), numpy (conditional)
missing module named numpy._core.void - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.vecmat - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.vecdot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.ushort - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.unsignedinteger - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ulonglong - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ulong - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.uintp - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.uintc - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.uint64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.uint32 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.uint16 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.uint - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ubyte - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.trunc - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.true_divide - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.transpose - imported by numpy._core (top-level), numpy.lib._function_base_impl (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.trace - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.timedelta64 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.tensordot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.tanh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.tan - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.swapaxes - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.sum - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.subtract - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.str_ - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.square - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.sqrt - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
missing module named numpy._core.spacing - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.sort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.sinh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.single - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.signedinteger - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.signbit - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.sign - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.short - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.rint - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.right_shift - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.result_type - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional), numpy.fft._pocketfft (top-level)
missing module named numpy._core.remainder - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.reciprocal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
missing module named numpy._core.radians - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.rad2deg - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.prod - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.power - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.positive - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.pi - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.outer - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.ones - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.object_ - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.number - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.not_equal - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.newaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.negative - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ndarray - imported by numpy._core (top-level), numpy.lib._utils_impl (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
missing module named numpy._core.multiply - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.moveaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.modf - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.mod - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.minimum - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.maximum - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.max - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.matrix_transpose - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.matvec - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.matmul - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.longdouble - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.long - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logical_xor - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logical_or - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logical_not - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logical_and - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logaddexp2 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.logaddexp - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.log2 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.log1p - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.log - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.linspace - imported by numpy._core (top-level), numpy.lib._index_tricks_impl (top-level), numpy (conditional)
missing module named numpy._core.less_equal - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.less - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.left_shift - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ldexp - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.lcm - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.isscalar - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.isnat - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
missing module named numpy._core.isnan - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.isfinite - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.intp - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.integer - imported by numpy._core (conditional), numpy (conditional), numpy.fft._helper (top-level)
missing module named numpy._core.intc - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.int8 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.int64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.int32 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.int16 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.inf - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.inexact - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.iinfo - imported by numpy._core (top-level), numpy.lib._twodim_base_impl (top-level), numpy (conditional)
missing module named numpy._core.hypot - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.hstack - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.heaviside - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.half - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.greater_equal - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.greater - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.gcd - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.frompyfunc - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.frexp - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.fmod - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.fmin - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.fmax - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.floor_divide - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.floor - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.floating - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.float_power - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.float32 - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.float16 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.finfo - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.fabs - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.expm1 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.exp - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.euler_gamma - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.errstate - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.equal - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.empty_like - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
missing module named numpy._core.empty - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy.fft._helper (top-level)
missing module named numpy._core.e - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.double - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.dot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.divmod - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.divide - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.diagonal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.degrees - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.deg2rad - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.datetime64 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.csingle - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.cross - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.count_nonzero - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.cosh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.cos - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.copysign - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.conjugate - imported by numpy._core (conditional), numpy (conditional), numpy.fft._pocketfft (top-level)
missing module named numpy._core.conj - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.complexfloating - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.complex64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
missing module named numpy._core.clongdouble - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.character - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.ceil - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.cdouble - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.cbrt - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bytes_ - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.byte - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bool_ - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bitwise_xor - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bitwise_or - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bitwise_count - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.bitwise_and - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.atleast_3d - imported by numpy._core (top-level), numpy.lib._shape_base_impl (top-level), numpy (conditional)
missing module named numpy._core.atleast_2d - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.atleast_1d - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.asarray - imported by numpy._core (top-level), numpy.lib._array_utils_impl (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level), numpy.fft._helper (top-level)
missing module named numpy._core.asanyarray - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.array_repr - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional)
missing module named numpy._core.array2string - imported by numpy._core (delayed), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.array - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
missing module named numpy._core.argsort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.arctanh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arctan2 - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arctan - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arcsinh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arcsin - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arccosh - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arccos - imported by numpy._core (conditional), numpy (conditional)
missing module named numpy._core.arange - imported by numpy._core (top-level), numpy.testing._private.utils (top-level), numpy (conditional), numpy.fft._helper (top-level)
missing module named numpy._core.amin - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.amax - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._core.all - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.testing._private.utils (delayed), numpy (conditional)
missing module named numpy._core.add - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
missing module named numpy._distributor_init_local - imported by numpy (optional), numpy._distributor_init (optional)

21683
build/main/xref-main.html Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
import os
import kp
import shutil
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QVBoxLayout, QWidget, QPushButton, QFileDialog, QHBoxLayout
from utils import preprocess_image, perform_inference, post_process_inference, process_image, cosine_similarity, compare_images_cosine_similarity, cluster_images_with_dbscan, list_image_files
class ConsoleWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Demo Console")
self.setGeometry(100, 100, 600, 400)
# Console area for log messages
self.text_edit = QTextEdit(self)
self.text_edit.setReadOnly(True)
# Button to start the declutter process
self.start_button = QPushButton("Select Directories and Start")
self.start_button.clicked.connect(self.select_directories_and_start)
# Layout setup
layout = QVBoxLayout()
layout.addWidget(self.text_edit)
layout.addWidget(self.start_button)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
# Variables to store directory paths
self.input_directory = ''
self.to_keep_directory = ''
self.to_delete_directory = ''
def print_message(self, message):
self.text_edit.append(message)
QApplication.processEvents() # Update the GUI immediately
def select_directories_and_start(self):
# Open directory dialog to select directories
self.input_directory = QFileDialog.getExistingDirectory(self, "Select Input Directory")
self.to_keep_directory = QFileDialog.getExistingDirectory(self, "Select 'To Keep' Directory")
self.to_delete_directory = QFileDialog.getExistingDirectory(self, "Select 'To Delete' Directory")
if self.input_directory and self.to_keep_directory and self.to_delete_directory:
self.print_message(f"Selected directories:\nInput: {self.input_directory}\nTo Keep: {self.to_keep_directory}\nTo Delete: {self.to_delete_directory}")
declutter_photo_album(self.input_directory, self.to_keep_directory, self.to_delete_directory, self)
def declutter_photo_album(input_directory, to_keep_directory, to_delete_directory, console):
def log(message):
console.print_message(message)
log("CONNECTING DEVICE")
DECLUTTER_MODEL_FILE_PATH = './resnet34_feature_extractor.nef'
PHOTO_QUALITY_SCORER_PATH = './photo_scorer_520.nef'
# Ensure output directories exist
os.makedirs(input_directory, exist_ok=True)
os.makedirs(to_keep_directory, exist_ok=True)
os.makedirs(to_delete_directory, exist_ok=True)
# Scan for devices
device_descriptors = kp.core.scan_devices()
if device_descriptors.device_descriptor_number > 0:
usb_port_id = device_descriptors.device_descriptor_list[0].usb_port_id
log(f"Device connected at USB port ID: {usb_port_id}")
else:
log('Error: no Kneron device connected.')
return
# Connect to device
device_group = kp.core.connect_devices(usb_port_ids=[22])
kp.core.set_timeout(device_group=device_group, milliseconds=5000)
SCPU_FW_PATH = '../../res/firmware/KL520/fw_scpu.bin'
NCPU_FW_PATH = '../../res/firmware/KL520/fw_ncpu.bin'
kp.core.load_firmware_from_file(device_group=device_group,
scpu_fw_path=SCPU_FW_PATH,
ncpu_fw_path=NCPU_FW_PATH)
# Filter low-quality images
log("FILTERING LOW QUALITY IMAGES")
model_nef_descriptor = kp.core.load_model_from_file(device_group=device_group,
file_path=PHOTO_QUALITY_SCORER_PATH)
to_keep_images = []
images = list_image_files(input_directory)
for image_file_path in images:
score = process_image(device_group, model_nef_descriptor, image_file_path)
log(f"Image: {image_file_path}, Score: {score}")
if score > 0.5:
log(" Low quality: recommend to delete")
shutil.copy(image_file_path, to_delete_directory)
else:
log(" Accepted quality image")
to_keep_images.append(image_file_path)
# Compare photo similarity
log("COMPARING PHOTO SIMILARITY")
model_nef_descriptor = kp.core.load_model_from_file(device_group=device_group,
file_path=DECLUTTER_MODEL_FILE_PATH)
images = to_keep_images
clusters = cluster_images_with_dbscan(images, device_group, model_nef_descriptor)
# Organize clustered images into directories
for cluster_index, cluster in enumerate(clusters):
cluster_dir = os.path.join(to_delete_directory, f"cluster_{cluster_index}")
os.makedirs(cluster_dir, exist_ok=True)
log(f"Cluster #{cluster_index}")
for image_file_path in cluster:
log(image_file_path)
shutil.copy(image_file_path, cluster_dir)
# Move images not in any cluster to 'to_keep' directory
non_clustered_images = set(images) - set(img for cluster in clusters for img in cluster)
for image_file_path in non_clustered_images:
shutil.copy(image_file_path, to_keep_directory)
# Decide which photos to keep in clusters
log("DECIDING WHICH PHOTO TO KEEP")
for cluster_index, cluster in enumerate(clusters):
cluster_scores = []
for image_file_path in cluster:
score = process_image(device_group, model_nef_descriptor, image_file_path)
cluster_scores.append((image_file_path, score))
# Sort by score in descending order and keep the top 2
cluster_scores.sort(key=lambda x: x[1], reverse=True)
top_photos = cluster_scores[:2]
log(f"In cluster {cluster_index}")
for image_file_path, _ in top_photos:
log(f"Keep image: {image_file_path}")
shutil.copy(image_file_path, to_keep_directory)
if __name__ == "__main__":
app = QApplication(sys.argv)
console = ConsoleWindow()
console.show()
sys.exit(app.exec_())

View File

@ -0,0 +1,296 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Demo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Set Up\n",
"prerequisites\n",
"- python 3.12\n",
"\n",
"``` shell\n",
"$ cd ./package/{platform}/\n",
"$ pip install KneronPLUS-2.3.0-py3-none-any.whl\n",
"$ pip install --force-reinstall KneronPLUS-2.3.0-py3-none-any.whl\n",
"$ pip install opencv-pythn\n",
"\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Connect KL520"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import cv2\n",
"import kp"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"22\n"
]
}
],
"source": [
"device_descriptors = kp.core.scan_devices()\n",
"\n",
"if 0 < device_descriptors.device_descriptor_number:\n",
" usb_port_id = device_descriptors.device_descriptor_list[0].usb_port_id\n",
" print(usb_port_id)\n",
"else:\n",
" print('Error: no Kneron device connect.')\n",
" exit(0)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"device_group = kp.core.connect_devices(usb_port_ids=[22])"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"kp.core.set_timeout(device_group=device_group,\n",
" milliseconds=5000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load firmware, model, and test image"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"SCPU_FW_PATH = '../../res/firmware/KL520/fw_scpu.bin'\n",
"NCPU_FW_PATH = '../../res/firmware/KL520/fw_ncpu.bin'\n",
"kp.core.load_firmware_from_file(device_group=device_group,\n",
" scpu_fw_path=SCPU_FW_PATH,\n",
" ncpu_fw_path=NCPU_FW_PATH)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"MODEL_FILE_PATH = './photo_scorer_520.nef'\n",
"model_nef_descriptor = kp.core.load_model_from_file(device_group=device_group,\n",
" file_path=MODEL_FILE_PATH)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### pre-processing"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"IMAGE_FILE_PATH = './test.jpg'\n",
"\n",
"img = cv2.imread(filename=IMAGE_FILE_PATH)\n",
"img_bgr565 = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2BGR565)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"generic_inference_input_descriptor = kp.GenericImageInferenceDescriptor(\n",
" model_id=model_nef_descriptor.models[0].id,\n",
" inference_number=0,\n",
" input_node_image_list=[\n",
" kp.GenericInputNodeImage(\n",
" image=img_bgr565,\n",
" image_format=kp.ImageFormat.KP_IMAGE_FORMAT_RGB565,\n",
" resize_mode=kp.ResizeMode.KP_RESIZE_ENABLE,\n",
" padding_mode=kp.PaddingMode.KP_PADDING_CORNER,\n",
" normalize_mode=kp.NormalizeMode.KP_NORMALIZE_KNERON\n",
" )\n",
" ]\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"header\": {\n",
" \"inference_number\": 0,\n",
" \"crop_number\": 0,\n",
" \"num_output_node\": 1,\n",
" \"product_id\": 256,\n",
" \"num_hw_pre_proc_info\": 1,\n",
" \"hw_pre_proc_info_list\": {\n",
" \"0\": {\n",
" \"img_width\": 1200,\n",
" \"img_height\": 800,\n",
" \"resized_img_width\": 224,\n",
" \"resized_img_height\": 149,\n",
" \"pad_top\": 0,\n",
" \"pad_bottom\": 75,\n",
" \"pad_left\": 0,\n",
" \"pad_right\": 0,\n",
" \"model_input_width\": 224,\n",
" \"model_input_height\": 224,\n",
" \"crop_area\": {\n",
" \"crop_box_index\": 0,\n",
" \"x\": 0,\n",
" \"y\": 0,\n",
" \"width\": 0,\n",
" \"height\": 0\n",
" }\n",
" }\n",
" }\n",
" },\n",
" \"raw_result\": {\n",
" \"buffer_size\": 388\n",
" }\n",
"}\n"
]
}
],
"source": [
"kp.inference.generic_image_inference_send(device_group=device_group,\n",
" generic_inference_input_descriptor=generic_inference_input_descriptor)\n",
"generic_raw_result = kp.inference.generic_image_inference_receive(device_group=device_group)\n",
"print(generic_raw_result)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[{\n",
" \"width\": 1,\n",
" \"height\": 1,\n",
" \"channel\": 1,\n",
" \"channels_ordering\": \"ChannelOrdering.KP_CHANNEL_ORDERING_CHW\",\n",
" \"num_data\": 1,\n",
" \"ndarray\": [\n",
" \"[[[[0.71443015]]]]\"\n",
" ]\n",
"}]\n"
]
}
],
"source": [
"inf_node_output_list = []\n",
"\n",
"for node_idx in range(generic_raw_result.header.num_output_node):\n",
" inference_float_node_output = kp.inference.generic_inference_retrieve_float_node(node_idx=node_idx,\n",
" generic_raw_result=generic_raw_result,\n",
" channels_ordering=kp.ChannelOrdering.KP_CHANNEL_ORDERING_CHW)\n",
" inf_node_output_list.append(inference_float_node_output)\n",
"\n",
"print(inf_node_output_list)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### post-processing\n",
"Kneron PLUS python version doesn't support on-NPU post-processing, so this step is demonstrated here"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The score of this photo is 0.7144301533699036\n"
]
}
],
"source": [
"import numpy as np\n",
"\n",
"nd_array = inf_node_output_list[0].ndarray\n",
"number = float(nd_array.flatten()[0])\n",
"\n",
"print(\"The score of this photo is\", number)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

720
demogui/main.py Normal file
View File

@ -0,0 +1,720 @@
import kp
import cv2, os, shutil, sys
from enum import Enum
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QPushButton,
QComboBox, QFileDialog, QMessageBox, QHBoxLayout, QDialog, QListWidget,
QScrollArea, QFrame, QListWidgetItem, QTextEdit)
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtMultimedia import QCamera, QCameraImageCapture, QCameraInfo, QMediaRecorder, QAudioRecorder
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtGui import QPixmap, QMovie
from PyQt5.QtCore import Qt, QTimer, QUrl
# Global Constants
UXUI_ASSETS = "../../uxui/"
WINDOW_SIZE = (1200, 900)
BACKGROUND_COLOR = "#143058"
SECONDARY_COLOR = "#1260E6"
DEVICE_BOX_STYLE = f"background-color: {BACKGROUND_COLOR}; padding: 20px; border-radius: 20px; padding: 10px 20px;"
BUTTON_STYLE = """
QPushButton {
background: transparent;
color: white;
border: 1px solid white;
border-radius: 20px;
padding: 10px 20px;
}
QPushButton:hover {
background-color: rgba(255, 255, 255, 50);
}
QPushButton:pressed {
background-color: rgba(255, 255, 255, 100);
}
"""
SQUARE_BUTTON_STYLE = "background: transparent; color: white; border: 1px transparent; border-radius: 10px; "
POPUP_SIZE_RATIO = 0.67
NO_DEVICE_GIF = UXUI_ASSETS + "no_device_temp.gif"
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.model_buttons = [
('Face Detection', self.run_face_detection),
('Gender/Age Detection', self.run_gender_age_detection),
('Object Detection', self.run_object_detection),
('Mask Detection', self.run_mask_detection),
('Image Project', self.start_image_project),
('Upload Model', self.upload_model)
]
self.connected_devices = [
]
self.input_directory = ""
self.to_keep_directory = ""
self.to_delete_directory = ""
self.image_directory = ""
self.label_directory = ""
self.video_widget = QVideoWidget(self)
self.camera = QCamera(QCameraInfo.defaultCamera())
self.image_capture = QCameraImageCapture(self.camera)
self.media_recorder = QMediaRecorder(self.camera)
self.audio_recorder = QAudioRecorder(self)
self.camera.setViewfinder(self.video_widget)
self.right_layout = QVBoxLayout()
self.left_layout = QVBoxLayout()
# TODO: find the correct mapping of the values
class K_(Enum):
KL520 = 256
KL720 = 720
KL720_L = 512 #legacy
KL530 = 530
KL832 = 832
KL730 = 732
KL630 = 630
KL540 = 540
def init_ui(self):
self.setGeometry(100, 100, *WINDOW_SIZE)
self.setWindowTitle('Innovedus AI Playground')
self.setStyleSheet(f"background-color: {BACKGROUND_COLOR};")
self.layout = QVBoxLayout(self)
self.show_welcome_label()
QTimer.singleShot(5000, self.show_device_popup_and_main_page)
def show_welcome_label(self):
welcome_label = QLabel(self)
welcome_pixmap = QPixmap(UXUI_ASSETS + "kneron_logo.png")
welcome_label.setPixmap(welcome_pixmap)
welcome_label.setAlignment(Qt.AlignCenter)
self.layout.addWidget(welcome_label)
def close_connection_page(self):
print("closing device connection page")
device_descriptors = kp.core.scan_devices()
if device_descriptors.device_descriptor_number > 0:
for device in device_descriptors.device_descriptor_list:
self.parse_and_store_devices(device_descriptors.device_descriptor_list)
kp.core.connect_devices(usb_port_ids=[device.usb_port_id])
self.load_firmware()
self.popup_window.close()
def load_firmware(self):
print("loading firmware")
for device in self.connected_devices:
device_group = kp.core.connect_devices(usb_port_ids=[device.get["usb_port_id"]])
kp.core.set_timeout(device_group=device_group, milliseconds=5000)
SCPU_FW_PATH = f'../../external/res/firmware/{device.get["product_id"]}/fw_scpu.bin'
NCPU_FW_PATH = f'../../external/res/firmware/{device.get["product_id"]}/fw_ncpu.bin'
kp.core.load_firmware_from_file(device_group=device_group,
scpu_fw_path=SCPU_FW_PATH,
ncpu_fw_path=NCPU_FW_PATH)
def show_error_popup(self, message):
error_dialog = QMessageBox.critical(self, "Error", message)
def parse_and_store_devices(self, devices):
for device in devices:
new_device = {
'usb_port_id': device.usb_port_id,
'product_id': device.product_id,
'kn_number': device.kn_number
}
print(device)
existing_device_index = next((index for (index, d) in enumerate(self.connected_devices)
if d['usb_port_id'] == new_device['usb_port_id']), None)
if existing_device_index is not None:
self.connected_devices[existing_device_index] = new_device
else:
self.connected_devices.append(new_device)
def check_available_device(self):
print("checking available devices")
device_descriptors = kp.core.scan_devices()
self.clear_device_layout(self.device_layout)
if device_descriptors.device_descriptor_number > 0:
if device_descriptors.device_descriptor_number > 0:
self.parse_and_store_devices(device_descriptors.device_descriptor_list)
self.display_devices(device_descriptors.device_descriptor_list)
else:
self.show_no_device_gif()
def get_dongle_type(self, product_id):
for dongle_type in self.K_:
if dongle_type.value == product_id:
return dongle_type
return None
def display_devices(self, device_descriptor_list):
hbox_layout = QHBoxLayout()
hbox_layout.setAlignment(Qt.AlignCenter)
for device in device_descriptor_list:
device_layout = QVBoxLayout()
box_layout = QVBoxLayout()
icon = QLabel()
pixmap = QPixmap(UXUI_ASSETS + "kneron_logo.png")
icon.setPixmap(pixmap.scaled(50, 50, Qt.KeepAspectRatio, Qt.SmoothTransformation))
print(device.product_id)
usb_type_label = QLabel(f"Device: {self.get_dongle_type(device.product_id)}")
usb_type_label.setAlignment(Qt.AlignCenter)
usb_type_label.setStyleSheet("color: white")
box_layout.addWidget(icon, alignment=Qt.AlignCenter)
box_layout.addWidget(usb_type_label)
box_widget = QWidget()
box_widget.setLayout(box_layout)
box_size = 200
box_widget.setFixedSize(box_size, box_size)
box_widget.setStyleSheet(DEVICE_BOX_STYLE)
usb_port_label = QLabel(f"KN number:\n{device.kn_number}")
usb_port_label.setAlignment(Qt.AlignLeft)
usb_port_label.setStyleSheet("color: white;")
label_icon_layout = QHBoxLayout()
small_icon = QSvgWidget(UXUI_ASSETS + "./Assets_svg/btn_dialog_device_disconnect_normal.svg")
small_icon.setFixedSize(30, 30)
label_icon_layout.addWidget(usb_port_label)
label_icon_layout.addWidget(small_icon, alignment=Qt.AlignRight)
device_layout.addWidget(box_widget)
device_layout.addLayout(label_icon_layout)
device_widget = QWidget()
device_widget.setLayout(device_layout)
hbox_layout.addWidget(device_widget)
self.device_layout.addLayout(hbox_layout)
def show_no_device_gif(self):
no_device_label = QLabel(self)
no_device_movie = QMovie(NO_DEVICE_GIF)
no_device_label.setMovie(no_device_movie)
no_device_movie.start()
no_device_label.setAlignment(Qt.AlignCenter)
self.device_layout.addWidget(no_device_label)
def show_device_connection_popup(self):
self.popup_window = QDialog(self)
self.popup_window.setWindowTitle("Device Connection")
self.popup_window.setFocusPolicy(Qt.StrongFocus)
popup_width = int(self.width() * POPUP_SIZE_RATIO)
popup_height = int(self.height() * POPUP_SIZE_RATIO)
self.popup_window.setGeometry(100, 100, popup_width, popup_height)
self.popup_window.setStyleSheet(f"background-color: {SECONDARY_COLOR};")
popup_layout = QVBoxLayout()
self.device_layout = QVBoxLayout()
popup_title = QHBoxLayout()
small_icon = QSvgWidget(UXUI_ASSETS + "./Assets_svg/ic_window_device.svg")
small_icon.setFixedSize(30, 30)
popup_title.addWidget(small_icon)
device_popup_label = QLabel("Device Connection", self.popup_window)
device_popup_label.setAlignment(Qt.AlignCenter)
popup_title.addWidget(device_popup_label)
popup_layout.addLayout(self.device_layout)
button_layout = QHBoxLayout()
refresh_button = QPushButton('Refresh')
refresh_button.clicked.connect(self.check_available_device)
refresh_button.setStyleSheet(BUTTON_STYLE)
button_layout.addWidget(refresh_button)
done_button = QPushButton('Done')
done_button.setStyleSheet(BUTTON_STYLE)
#done_button.clicked.connect(self.close_connection_page)
done_button.clicked.connect(lambda: self.close_connection_page())
button_layout.addWidget(done_button)
popup_layout.addLayout(button_layout)
self.popup_window.setLayout(popup_layout)
self.popup_window.setModal(True)
self.setEnabled(False)
self.popup_window.finished.connect(lambda: self.setEnabled(True))
self.popup_window.show()
self.check_available_device()
def show_device_popup_and_main_page(self):
self.show_device_connection_popup()
self.popup_window.finished.connect(self.main_page)
def clear_device_layout(self, layout):
for i in reversed(range(layout.count())):
layout.itemAt(i).widget().deleteLater()
def clear_layout(self):
for i in reversed(range(self.device_layout.count())):
self.device_layout.itemAt(i).widget().deleteLater()
def create_frame(self, title, icon_path):
frame = QFrame(self)
frame.setStyleSheet(f"border: none; background: {SECONDARY_COLOR}; border-radius: 20px;")
layout = QVBoxLayout(frame)
title_layout = QHBoxLayout()
title_icon = QSvgWidget(icon_path)
title_icon.setFixedSize(40, 40)
title_layout.addWidget(title_icon)
title_label = QLabel(title)
title_label.setStyleSheet("color: white;")
title_layout.addWidget(title_label)
layout.addLayout(title_layout)
return frame
def add_model_buttons(self, layout):
for model_name, run_function in self.model_buttons:
button = QPushButton(model_name)
button.clicked.connect(run_function)
button.setStyleSheet("""
QPushButton {
color: white;
border: 2px solid white;
border-radius: 10px;
padding: 10px;
background-color: transparent;
}
QPushButton:hover {
background-color: rgba(255, 255, 255, 50);
}
QPushButton:pressed {
background-color: rgba(255, 255, 255, 100);
}
""")
layout.addWidget(button)
def start_camera(self):
print("opening camera")
self.right_layout.replaceWidget(self.canvas_label, self.video_widget)
self.canvas_label.hide()
self.camera.start()
def stop_camera(self):
self.camera.stop()
self.right_layout.replaceWidget(self.video_widget, self.canvas_label)
self.video_widget.hide()
self.canvas_label.show()
# TODO: implement these functions and add button state/style change
def record_video(self):
output_file = "output_video.mp4"
self.media_recorder.setOutputLocation(QUrl.fromLocalFile(os.path.abspath(output_file)))
self.media_recorder.record()
def stop_recording(self):
self.media_recorder.stop()
def record_audio(self):
audio_output_file = "output_audio.wav"
self.audio_recorder.setOutputLocation(QUrl.fromLocalFile(os.path.abspath(audio_output_file)))
self.audio_recorder.record()
def stop_audio(self):
self.audio_recorder.stop()
def take_screenshot(self):
self.image_capture.capture()
self.image_capture.imageCaptured.connect(self.process_capture)
def process_capture(self, requestId, image):
file_name = f"screenshot_{requestId}.png"
image.save(file_name)
print(f"Screenshot saved as {file_name}")
def run_face_detection(self):
self.start_camera()
print("Running Face Detection")
def run_gender_age_detection(self):
self.start_camera()
print("Running Gender/Age Detection")
def run_object_detection(self):
self.start_camera()
print("Running Object Detection")
def run_mask_detection(self):
self.start_camera()
print("Running Mask Detection")
def choose_folder(self):
self.input_directory = QFileDialog.getExistingDirectory(self, "Select Input Directory")
self.to_keep_directory = QFileDialog.getExistingDirectory(self, "Select 'To Keep' Directory")
self.to_delete_directory = QFileDialog.getExistingDirectory(self, "Select 'To Delete' Directory")
if self.input_directory and self.to_keep_directory and self.to_delete_directory:
print(f"Selected directories:\nInput: {self.input_directory}\nTo Keep: {self.to_keep_directory}\nTo Delete: {self.to_delete_directory}")
def create_folder_button(self):
folder_button_widget = QWidget()
folder_button_layout = QVBoxLayout()
text_label = QLabel("Image")
text_label.setAlignment(Qt.AlignCenter)
text_label.setStyleSheet("color: white;")
folder_button_layout.addWidget(text_label)
folder_button_widget.setLayout(folder_button_layout)
folder_button_widget.setStyleSheet(f"""
QWidget {{
background-color: {SECONDARY_COLOR};
border: 2px solid white;
border-radius: 10px;
padding: 10px;
min-width: 100px;
min-height: 100px;
}}
""")
return folder_button_widget
def process_image_project(self):
print("processing_image_project")
def start_image_project(self):
print("running image project")
self.popup_window = QDialog(self)
self.popup_window.setWindowTitle("Choose Folder")
popup_width = int(self.width() * POPUP_SIZE_RATIO)
popup_height = int(self.height() * POPUP_SIZE_RATIO)
self.popup_window.setGeometry(100, 100, popup_width, popup_height)
self.popup_window.setStyleSheet(f"background-color: {SECONDARY_COLOR};")
popup_layout = QVBoxLayout()
self.device_layout = QVBoxLayout()
cust_label = QLabel("Customization", self.popup_window)
cust_label.setAlignment(Qt.AlignCenter)
cust_label.setStyleSheet("color: white")
popup_layout.addWidget(cust_label)
popup_layout.addLayout(self.device_layout)
folder_icon = QSvgWidget(UXUI_ASSETS + "./Assets_svg/ic_customization_upload_folder.svg")
folder_icon.setFixedSize(100, 100)
upload_icon = QSvgWidget(UXUI_ASSETS + "./Assets_svg/bt_function_upload_normal.svg")
upload_icon.setFixedSize(40, 40)
folder_button_widget = QWidget()
folder_button_layout = QVBoxLayout()
text_label = QLabel("Image")
text_label.setAlignment(Qt.AlignCenter)
text_label.setStyleSheet("color: white; border: none")
folder_button_layout.addWidget(text_label)
folder_button_layout.addWidget(folder_icon)
description_label = QLabel("Upload or drag files")
description_label.setAlignment(Qt.AlignCenter)
description_label.setStyleSheet("color: white; border: none")
folder_button_layout.addWidget(description_label)
folder_button_layout.addWidget(upload_icon)
folder_button_layout.setAlignment(Qt.AlignCenter)
folder_button_widget.setLayout(folder_button_layout)
folder_frame = QFrame()
folder_frame.setStyleSheet(f"""
QFrame {{
border: 2px solid white;
border-radius: 10px;
padding: 10px;
background-color: {SECONDARY_COLOR};
}}
""")
folder_frame.setLayout(QVBoxLayout())
folder_frame.layout().addWidget(folder_button_widget)
folder_icon2 = QSvgWidget(UXUI_ASSETS + "./Assets_svg/ic_customization_upload_folder.svg")
folder_icon2.setFixedSize(100, 100)
upload_icon2 = QSvgWidget(UXUI_ASSETS + "./Assets_svg/bt_function_upload_normal.svg")
upload_icon2.setFixedSize(40, 40)
folder_button_widget2 = QWidget()
folder_button_layout2 = QVBoxLayout()
text_label2 = QLabel("Label")
text_label2.setAlignment(Qt.AlignCenter)
text_label2.setStyleSheet("color: white; border: none")
folder_button_layout2.addWidget(text_label2)
folder_button_layout2.addWidget(folder_icon2)
folder_button_layout2.setAlignment(Qt.AlignCenter)
description_label2 = QLabel("Upload or drag files")
description_label2.setAlignment(Qt.AlignCenter)
description_label2.setStyleSheet("color: white; border: none")
folder_button_layout2.addWidget(description_label2)
folder_button_layout2.addWidget(upload_icon2)
folder_button_widget2.setLayout(folder_button_layout2)
folder_frame2 = QFrame()
folder_frame2.setStyleSheet(f"""
QFrame {{
border: 2px solid white;
border-radius: 10px;
padding: 10px;
background-color: {SECONDARY_COLOR};
}}
""")
folder_frame2.setLayout(QVBoxLayout())
folder_frame2.layout().addWidget(folder_button_widget2)
folder_buttons_layout = QHBoxLayout()
folder_buttons_layout.addWidget(folder_frame)
folder_buttons_layout.addWidget(folder_frame2)
popup_layout.addLayout(folder_buttons_layout)
button_layout = QHBoxLayout()
self.cancel_button = QPushButton('Cancel', self.popup_window)
self.cancel_button.clicked.connect(self.popup_window.close)
self.cancel_button.setStyleSheet(BUTTON_STYLE)
button_layout.addWidget(self.cancel_button)
self.done_button = QPushButton('Done', self.popup_window)
self.done_button.setStyleSheet(BUTTON_STYLE)
self.done_button.clicked.connect(self.process_image_project)
button_layout.addWidget(self.done_button)
popup_layout.addLayout(button_layout)
self.popup_window.setLayout(popup_layout)
self.popup_window.setModal(True)
self.setEnabled(False)
self.popup_window.finished.connect(lambda: self.setEnabled(True))
self.popup_window.show()
def upload_model(self):
print("Uploading Model")
def main_page(self):
self.clear_device_layout(self.layout)
self.setWindowTitle('Innovedus AI Playground')
self.setGeometry(100, 100, *WINDOW_SIZE)
main_layout = QHBoxLayout()
top_nav = QHBoxLayout()
welcome_label = QLabel(self)
welcome_pixmap = QPixmap(UXUI_ASSETS + "kneron_logo.png").scaled(150, 150, Qt.KeepAspectRatio)
welcome_label.setPixmap(welcome_pixmap)
top_nav.addWidget(welcome_label, alignment=Qt.AlignLeft)
top_nav.addStretch()
settings_button = QPushButton("Settings", self)
settings_button.setStyleSheet(BUTTON_STYLE)
top_nav.addWidget(settings_button, alignment=Qt.AlignRight)
self.layout.addLayout(top_nav)
left_widget = QWidget()
left_widget.setLayout(self.left_layout)
left_widget.setFixedWidth(self.geometry().width() // 3)
right_widget = QWidget()
right_widget.setLayout(self.right_layout)
right_widget.setFixedWidth(self.geometry().width() * 2 // 3)
main_layout.addWidget(left_widget)
main_layout.addWidget(right_widget)
self.layout.addLayout(main_layout)
self.setLayout(self.layout)
self.create_device_layout()
self.create_right_layout()
def show_device_details(self):
print("show_device_details")
def create_device_layout(self):
devices_frame = self.create_frame("Device", UXUI_ASSETS + "./Assets_svg/ic_window_device.svg")
devices_frame_layout = QVBoxLayout()
self.device_list = QListWidget(self)
print(self.connected_devices)
for device in self.connected_devices:
usb_port_id = device.get("usb_port_id")
product_id = device.get("product_id")
kn_number = device.get("kn_number")
h_layout = QHBoxLayout()
icon = QSvgWidget(UXUI_ASSETS + "./Assets_svg/ic_window_device.svg")
icon.setFixedSize(40, 40)
h_layout.addWidget(icon)
text_layout = QVBoxLayout()
line1_label = QLabel(f"Dongle: {product_id}")
line1_label.setStyleSheet("font-weight: bold; color: white;")
text_layout.addWidget(line1_label)
line2_label = QLabel(f"KN number: {kn_number}")
line2_label.setStyleSheet("color: white;")
text_layout.addWidget(line2_label)
h_layout.addLayout(text_layout)
item_widget = QWidget()
item_widget.setLayout(h_layout)
list_item = QListWidgetItem()
list_item.setSizeHint(item_widget.sizeHint())
self.device_list.addItem(list_item)
self.device_list.setItemWidget(list_item, item_widget)
devices_frame_layout.addWidget(self.device_list)
detail_button = QPushButton("Details", self)
detail_button.clicked.connect(self.show_device_details)
devices_frame_layout.addWidget(detail_button)
devices_frame.setLayout(devices_frame_layout)
self.left_layout.addWidget(devices_frame)
self.models_frame = self.create_frame("AI Toolbox", UXUI_ASSETS + "./Assets_svg/ic_window_toolbox.svg")
models_layout = QVBoxLayout(self.models_frame)
self.models_frame.setLayout(models_layout)
self.add_model_buttons(self.models_frame.layout())
self.left_layout.addWidget(self.models_frame)
def create_right_layout(self):
self.canvas_label = QLabel("Canvas Area (Camera Screen)", self)
self.canvas_label.setAlignment(Qt.AlignCenter)
self.canvas_label.setStyleSheet("border: 1px transparent; background: gray; border-radius: 20px; ")
self.right_layout.addWidget(self.canvas_label)
button_overlay_layout = QVBoxLayout()
button_overlay_layout.setContentsMargins(0, 0, 0, 0)
self.create_square_buttons(button_overlay_layout)
button_overlay_widget = QWidget(self)
button_overlay_widget.setLayout(button_overlay_layout)
button_overlay_widget.setStyleSheet(f"background: {SECONDARY_COLOR}; border-radius: 20px; padding: 10px;")
button_overlay_widget.setFixedHeight(150)
self.right_layout.addWidget(button_overlay_widget, alignment=Qt.AlignBottom | Qt.AlignRight)
def create_square_buttons(self, layout):
square_buttons_info = [
('video', UXUI_ASSETS + "./Assets_svg/ic_recording_camera.svg"),
('voice', UXUI_ASSETS + "./Assets_svg/ic_recording_voice.svg"),
('screenshot', UXUI_ASSETS + "./Assets_svg/bt_function_screencapture_normal.svg"),
]
for button_name, icon_path in square_buttons_info:
button = QPushButton(self)
button.setFixedSize(50, 50)
button.setStyleSheet(SQUARE_BUTTON_STYLE)
button_layout = QHBoxLayout(button)
button_layout.setContentsMargins(0, 0, 0, 0)
icon = QSvgWidget(icon_path)
icon.setFixedSize(40, 40)
button_layout.addWidget(icon)
layout.addWidget(button)
def upload_model(self):
model_file, _ = QFileDialog.getOpenFileName(self, "Upload Model", "", "NEF Files (*.nef)")
if model_file:
if model_file.endswith('.nef'):
model_name = os.path.basename(model_file)
self.model_buttons.insert(-1, (model_name, self.run_uploaded_model))
print(f"Model uploaded: {model_name}")
self.refresh_model_buttons()
else:
self.show_error_popup("Invalid file format. Please upload a .nef file.")
def refresh_model_buttons(self):
layout = self.models_frame.layout()
for i in reversed(range(layout.count())):
widget_to_remove = layout.itemAt(i).widget()
if widget_to_remove is not None:
widget_to_remove.deleteLater()
self.add_model_buttons(layout)
def run_uploaded_model(self):
print("Running uploaded model")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

160
demogui/utils.py Normal file
View File

@ -0,0 +1,160 @@
import os
import cv2
import kp
import numpy as np
import numpy as np
from sklearn.cluster import DBSCAN
# -------------------- General Dongle Connection -------------------------------#
def connect_and_load_firmware(device_descriptors):
# device_descriptors = kp.core.scan_devices()
if 0 < device_descriptors.device_descriptor_number:
for device in device_descriptors.device_descriptor_list:
usb_port_id = device.usb_port_id
device_group = kp.core.connect_devices(usb_port_ids=[22])
kp.core.set_timeout(device_group=device_group,
milliseconds=5000)
SCPU_FW_PATH = '../../res/firmware/KL520/fw_scpu.bin'
NCPU_FW_PATH = '../../res/firmware/KL520/fw_ncpu.bin'
kp.core.load_firmware_from_file(device_group=device_group,
scpu_fw_path=SCPU_FW_PATH,
ncpu_fw_path=NCPU_FW_PATH)
else:
print('Error: no Kneron device connect.')
exit(0)
def load_firmware():
print("loading firmware")
def list_image_files(directory):
"""List all image files in a given directory."""
valid_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.gif')
return [os.path.join(directory, f) for f in os.listdir(directory) if f.lower().endswith(valid_extensions)]
# -------------------- Decluttering & Photo Quality Model -------------------------------#
def preprocess_image(image_file_path):
maxbytes = 500000
file_size = os.path.getsize(image_file_path)
img = cv2.imread(filename=image_file_path)
if file_size > maxbytes:
scale_factor = (maxbytes / file_size) ** 0.5
new_width = int(img.shape[1] * scale_factor)
new_height = int(img.shape[0] * scale_factor)
if new_width % 2 != 0:
new_width += 1
img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)
else:
if img.shape[1] % 2 != 0:
img = cv2.resize(img, (img.shape[1] + 1, img.shape[0]), interpolation=cv2.INTER_AREA)
img_bgr565 = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2BGR565)
return img_bgr565
def perform_inference(device_group, model_nef_descriptor, img_bgr565):
generic_inference_input_descriptor = kp.GenericImageInferenceDescriptor(
model_id=model_nef_descriptor.models[0].id,
inference_number=0,
input_node_image_list=[
kp.GenericInputNodeImage(
image=img_bgr565,
image_format=kp.ImageFormat.KP_IMAGE_FORMAT_RGB565,
resize_mode=kp.ResizeMode.KP_RESIZE_ENABLE,
padding_mode=kp.PaddingMode.KP_PADDING_CORNER,
normalize_mode=kp.NormalizeMode.KP_NORMALIZE_KNERON
)
]
)
kp.inference.generic_image_inference_send(device_group=device_group,
generic_inference_input_descriptor=generic_inference_input_descriptor)
generic_raw_result = kp.inference.generic_image_inference_receive(device_group=device_group)
inf_node_output_list = []
for node_idx in range(generic_raw_result.header.num_output_node):
inference_float_node_output = kp.inference.generic_inference_retrieve_float_node(
node_idx=node_idx,
generic_raw_result=generic_raw_result,
channels_ordering=kp.ChannelOrdering.KP_CHANNEL_ORDERING_CHW
)
inf_node_output_list.append(inference_float_node_output)
return inf_node_output_list
def post_process_inference(inf_node_output_list):
"""Processes the inference output and returns a mean score."""
data = inf_node_output_list[0]
raw_ndarray = data.ndarray
if isinstance(raw_ndarray, np.ndarray):
ndarray_np = raw_ndarray
else:
ndarray_np = np.array(raw_ndarray)
ndarray_np = ndarray_np.flatten()
ndarray_np = ndarray_np.reshape((data.channel, data.height, data.width))
ndarray_np = ndarray_np.flatten()
result = np.mean(ndarray_np) # Mean score
return result
def process_image(device_group, model_nef_descriptor, image_file_path):
"""Full pipeline: preprocess image, perform inference, and post-process to get a score."""
img_bgr565 = preprocess_image(image_file_path)
inf_node_output_list = perform_inference(device_group, model_nef_descriptor, img_bgr565)
nd_array = inf_node_output_list[0].ndarray
number = float(nd_array.flatten()[0])
return number
def cosine_similarity(tensor1, tensor2):
"""Compute the cosine similarity between two tensors."""
dot_product = np.dot(tensor1, tensor2)
norm1 = np.linalg.norm(tensor1)
norm2 = np.linalg.norm(tensor2)
return dot_product / (norm1 * norm2)
def compare_images_cosine_similarity(image_paths, device_group, model_nef_descriptor):
"""Compare the cosine similarity between feature tensors of photos in the given image file paths."""
num_images = len(image_paths)
features = []
for image_path in image_paths:
feature = process_image(device_group, model_nef_descriptor, image_path)
features.append(feature)
similarity_matrix = np.zeros((num_images, num_images))
for i in range(num_images):
for j in range(num_images):
if i != j:
similarity_matrix[i, j] = cosine_similarity(features[i], features[j])
else:
similarity_matrix[i, j] = 1.0
return similarity_matrix
def cluster_images_with_dbscan(image_paths, feature_extractor, model_nef_descriptor, similarity_threshold=0.8, min_samples=2):
"""Cluster images based on cosine similarity using DBSCAN and return clusters as arrays of file paths."""
similarity_matrix = compare_images_cosine_similarity(image_paths, feature_extractor, model_nef_descriptor)
distance_matrix = 1 - similarity_matrix
dbscan = DBSCAN(eps=1-similarity_threshold, min_samples=min_samples, metric='precomputed')
labels = dbscan.fit_predict(distance_matrix)
clusters = []
unique_labels = set(labels)
for label in unique_labels:
if label != -1:
cluster = [image_paths[i] for i in range(len(labels)) if labels[i] == label]
clusters.append(cluster)
return clusters

BIN
dist/Output/mysetup.exe vendored Normal file

Binary file not shown.

BIN
dist/main.exe vendored Normal file

Binary file not shown.

64
dist/test.iss vendored Normal file
View File

@ -0,0 +1,64 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Kneron Academy"
#define MyAppVersion "2.0"
#define MyAppPublisher "Innovedus Inc."
#define MyAppURL "https://www.example.com/"
#define MyAppExeName "main.exe"
[Setup]
; 唯一的 AppId請勿在其他應用程式中重複使用
AppId={{0894596D-D78B-4D8C-97CC-D90FE98E26E0}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
; 僅允許在 x64 或 Windows 11 on Arm 上安裝
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
DisableProgramGroupPage=yes
; 若移除此行則為系統管理員模式安裝 (安裝給所有使用者)
PrivilegesRequired=lowest
OutputBaseFilename=mysetup
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
; 定義配對元件,讓使用者選擇是否安裝預設的 Script 與 Model
[Components]
Name: "pair1"; Description: "Fire Detection";
Name: "pair2"; Description: "Photo_quality";
[Files]
; 安裝主要執行檔到 {app} 目錄
Source: "C:\Users\mason\Code\demo_gui\dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
; --- 配對1 ---
; pair 1
Source: "C:\Users\mason\Downloads\Kneron_Academy\utils\models\fire_detection_520.nef"; DestDir: "{localappdata}\Kneron_Academy\utils\models\fire_detection_520.nef"; Components: pair1; Flags: ignoreversion recursesubdirs
Source: "C:\Users\mason\Downloads\Kneron_Academy\utils\scripts\fire_detection_520.py"; DestDir: "{localappdata}\Kneron_Academy\utils\scripts\fire_detection_520.py"; Components: pair1; Flags: ignoreversion recursesubdirs
; pair 2
Source: "C:\Users\mason\Downloads\Kneron_Academy\utils\models\photo_scorer_520.nef"; DestDir: "{localappdata}\Kneron_Academy\utils\models\photo_scorer_520.nef"; Components: pair2; Flags: ignoreversion recursesubdirs
Source: "C:\Users\mason\Downloads\Kneron_Academy\utils\scripts\photo_quality_520.py"; DestDir: "{localappdata}\Kneron_Academy\utils\scripts\photo_quality_520.py"; Components: pair2; Flags: ignoreversion recursesubdirs
[Dirs]
; 如有需要隱藏這些資料夾,設定隱藏屬性
Name: "{localappdata}\Kneron_Academy\utils\scripts"; Attribs: hidden
Name: "{localappdata}\Kneron_Academy\utils\models"; Attribs: hidden
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

4
hook-kp.py Normal file
View File

@ -0,0 +1,4 @@
from PyInstaller.utils.hooks import collect_data_files
# 收集 kp package 內所有資料檔(如非 .py 檔案)
datas = collect_data_files('kp')

13
main.py Normal file
View File

@ -0,0 +1,13 @@
import sys
from PyQt5.QtWidgets import QApplication
from src.views.mainWindows import MainWindow
from src.config import APP_NAME, WINDOW_SIZE
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

38
main.spec Normal file
View File

@ -0,0 +1,38 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[('uxui', 'uxui'), ('src', 'src'), ('C:\\Users\\mason\\miniconda3\\envs\\resnet\\Lib\\site-packages\\kp\\lib', 'kp\\lib')],
hiddenimports=[],
hookspath=['hooks'],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

80
src/config.py Normal file
View File

@ -0,0 +1,80 @@
from enum import Enum
import os
APPDATA_PATH = os.environ.get("LOCALAPPDATA")
# 取得專案根目錄的絕對路徑並設定 UXUI_ASSETS 為絕對路徑
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
UXUI_ASSETS = os.path.join(PROJECT_ROOT, "uxui", "")
MODEL = os.path.join(APPDATA_PATH,"Kneron_Academy", "utils", "models", "")
SCRIPT = os.path.join(APPDATA_PATH, "Kneron_Academy", "utils", "scripts", "")
SCRIPT_CONFIG = os.path.join(APPDATA_PATH, "Kneron_Academy", "utils", "configs.json")
UPLOAD_DIR = os.path.join(APPDATA_PATH, "Kneron_Academy", "uploads")
FW_DIR = os.path.join(APPDATA_PATH, "Kneron_Academy", "utils", "firmware")
# Global Constants
APP_NAME = "Innovedus AI Playground"
WINDOW_SIZE = (1200, 900)
BACKGROUND_COLOR = "#143058"
SECONDARY_COLOR = "#005ED7"
MASK_STYLE = f"background-color: rgba(0, 0, 0, 128);"
DEVICE_BOX_STYLE = f"background-color: {BACKGROUND_COLOR}; padding: 20px; border-radius: 20px; padding: 10px 20px;"
BUTTON_STYLE = """
QPushButton {
background: transparent;
color: white;
border: 2px solid white;
border-radius: 15px;
padding: 5px 10px;
}
QPushButton:hover {
background-color: rgba(255, 255, 255, 50);
}
QPushButton:pressed {
background-color: rgba(255, 255, 255, 100);
}
"""
SQUARE_BUTTON_STYLE = "background: transparent; color: white; border: 1px transparent; border-radius: 10px; "
POPUP_SIZE_RATIO = 0.67
NO_DEVICE_GIF = UXUI_ASSETS + "no_device_temp.gif"
# Firmware Path Relatives
FIRMWARE_PATHS = {
"scpu": "../../res/firmware/fw_scpu.bin",
"ncpu": "../../res/firmware/fw_ncpu.bin",
}
# MODEL_BUTTON = [
# ('Face Detection', self.run_face_detection),
# ('Gender/Age Detection', self.run_gender_age_detection),
# ('Object Detection', self.run_object_detection),
# ('Mask Detection', self.run_mask_detection),
# ('Image Project', self.start_image_project),
# ('Upload Model', self.upload_model)
# ]
# Model Inference Parameter
MODEL_TIMEOUT = 5000
# TODO: Mapping of the values
class DeviceType(Enum):
KL520 = 256
# KL720 = 720
KL720 = 1824
KL720_L = 512
KL530 = 530
KL832 = 832
KL730 = 732
KL630 = 630
KL540 = 540
DongleModelMap = {
"0x100": "KL520", # product_id "0x100" 對應到 520 系列
"0x720": "KL720", # product_id "0x720" 對應到 720 系列
}
DongleIconMap = {
"0x100": "ic_dongle_520.png",
"0x720": "ic_dongle_720.png"
}

View File

@ -0,0 +1,32 @@
import kp
from typing import List, Dict
class DeviceController:
def __init__(self):
self.connected_devices = []
def scan_devices(self):
return kp.core.scan_devices()
def connect_device(self, usb_port_id: int):
device_group = kp.core.connect_devices(usb_port_ids=[usb_port_id])
kp.core.set_timeout(device_group=device_group, milliseconds=5000)
return device_group
def load_firmware(self, device_group, product_id: int):
SCPU_FW_PATH = f'../../external/res/firmware/{product_id}/fw_scpu.bin'
NCPU_FW_PATH = f'../../external/res/firmware/{product_id}/fw_ncpu.bin'
kp.core.load_firmware_from_file(
device_group=device_group,
scpu_fw_path=SCPU_FW_PATH,
ncpu_fw_path=NCPU_FW_PATH
)
def parse_device_info(self, device) -> Dict:
return {
'usb_port_id': device.usb_port_id,
'product_id': device.product_id,
'kn_number': device.kn_number
}

View File

View File

@ -0,0 +1,48 @@
import kp
def check_available_device():
try:
print("checking available devices")
device_descriptors = kp.core.scan_devices()
return device_descriptors
except Exception as e:
print(f"Error scanning devices: {e}")
# 返回一個空的設備描述符或模擬數據
class EmptyDescriptor:
def __init__(self):
self.device_descriptor_number = 0
self.device_descriptor_list = []
return EmptyDescriptor()
# def check_available_device():
# print("checking available devices")
# # 模擬設備描述符
# device_descriptors = [
# {
# "usb_port_id": 4,
# "vendor_id": "0x3231",
# "product_id": "0x720",
# "link_speed": "UsbSpeed.KP_USB_SPEED_SUPER",
# "kn_number": "0xB306224C",
# "is_connectable": True,
# "usb_port_path": "4-1",
# "firmware": "KDP2 Comp/F"
# },
# {
# "usb_port_id": 5,
# "vendor_id": "0x3231",
# "product_id": "0x520",
# "link_speed": "UsbSpeed.KP_USB_SPEED_SUPER",
# "kn_number": "0xB306224C",
# "is_connectable": True,
# "usb_port_path": "4-1",
# "firmware": "KDP2 Comp/F"
# }
# ]
# return device_descriptors
# def get_dongle_type(self, product_id):
# for dongle_type in self.K_:
# if dongle_type.value == product_id:
# return dongle_type
# return None

View File

@ -0,0 +1,14 @@
import kp
import cv2, os, shutil, sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QPushButton,
QComboBox, QFileDialog, QMessageBox, QHBoxLayout, QDialog, QListWidget,
QScrollArea, QFrame, QListWidgetItem, QTextEdit)
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtMultimedia import QCamera, QCameraImageCapture, QCameraInfo, QMediaRecorder, QAudioRecorder
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtGui import QPixmap, QMovie
from PyQt5.QtCore import Qt, QTimer, QUrl
from ..config import UXUI_ASSETS, WINDOW_SIZE, BACKGROUND_COLOR
def show_error_popup(self, message):
error_dialog = QMessageBox.critical(self, "Error", message)

View File

@ -0,0 +1,84 @@
import os, subprocess, shlex
from pathlib import Path
'''
執行已經寫好的腳本 並提供主程式檢查目前下載的 python script
'''
def list_scripts(directory, extensions):
path = Path(directory)
if not path.exists() or not path.is_dir():
print(f"資料夾 {directory} 不存在或不是一個資料夾。")
return []
return [f for f in path.iterdir() if f.is_file() and f.suffix in extensions]
def run_script(args, filename):
if not os.path.exists(filename):
print("沒有找到可執行的程式檔案。")
return
return execute_script(args, filename)
def execute_script(args, script_path):
try:
if Path(script_path).suffix == '.py':
# 將 args 解析成命令列參數列表(若沒有參數則傳空列表), 使用者如果需要傳遞包含空白的參數,可以透過引號來保護該參數 (['arg1', 'arg with spaces', 'arg3'])
arg_list = shlex.split(args) if args else []
# 將參數加入命令列中,目標 script 可透過 sys.argv 讀取
process = subprocess.Popen(
['python', str(script_path)] + arg_list,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
stdout, stderr = process.communicate()
if stderr:
print(f"執行警告/錯誤: {stderr}")
return stdout
else:
print(f"不支援的檔案類型: {script_path}")
return None
except subprocess.CalledProcessError as e:
print(f"執行 {script_path} 時發生錯誤: {e}")
return None
except Exception as e:
print(f"執行 {script_path} 時發生未預期的錯誤: {e}")
return None
'''
Test the script service including execute_script, run_script, and list_scripts
def main():
directory = './test_script' # 修改為您的腳本目錄
extensions = ['.py']
# 列出所有可執行的腳本
scripts = list_scripts(directory, extensions)
if not scripts:
print("找不到可執行的腳本。")
return
# 顯示可用腳本
print("可用的腳本:")
for i, script in enumerate(scripts, 1):
print(f"{i}. {script.name}")
# 選擇腳本
try:
choice = int(input("請選擇要執行的腳本編號: ")) - 1
if 0 <= choice < len(scripts):
selected_script = scripts[choice]
# 取得輸入參數 (以空白分隔)
args = input("請輸入要傳遞給腳本的參數 (以空白分隔): ")
# 執行腳本並獲取結果
result = run_script(args, selected_script)
if result:
print(f"執行結果:\n{result}")
else:
print("無效的選擇。")
except ValueError:
print("請輸入有效的數字。")
if __name__ == "__main__":
main()
'''

View File

@ -0,0 +1,24 @@
def process_input(input_str):
# 檢查輸入是否為空
if not input_str:
return "錯誤:沒有輸入參數"
# 檢查輸入是否為數字
try:
number = float(input_str)
# 進行簡單計算
result = number * 2
return f"輸入參數 {input_str} 的兩倍是:{result}"
except ValueError:
# 如果不是數字,就當作字串處理
return f"輸入的字串是:{input_str}\n反轉後是:{input_str[::-1]}"
if __name__ == "__main__":
import sys
# 從標準輸入讀取參數
input_data = input()
# 處理輸入並輸出結果
result = process_input(input_data)
print(result)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,70 @@
# srcs/views/device_connection_popup.py
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QListWidget, QListWidgetItem
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtCore import Qt
from ..config import UXUI_ASSETS, SECONDARY_COLOR, BUTTON_STYLE
import os
class DeviceConnectionPopup(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.init_ui()
def init_ui(self):
# 設定彈出視窗的大小和樣式
self.setFixedSize(int(self.parent.width() * 0.67), int(self.parent.height() * 0.67))
self.setStyleSheet(f"""
QWidget {{
background-color: {SECONDARY_COLOR};
border-radius: 20px;
padding: 20px;
}}
""")
layout = QVBoxLayout(self)
# 標題列
title_layout = QHBoxLayout()
title_layout.setAlignment(Qt.AlignCenter)
# 容器來放置圖示和標籤
title_container = QWidget()
container_layout = QHBoxLayout(title_container)
container_layout.setSpacing(10)
# 添加圖示
device_icon = QSvgWidget(os.path.join(UXUI_ASSETS, "Assets_svg/ic_window_device.svg"))
device_icon.setFixedSize(35, 35)
container_layout.addWidget(device_icon)
# 添加標籤
popup_label = QLabel("Device Connection")
popup_label.setStyleSheet("color: white; font-size: 25px;")
container_layout.addWidget(popup_label)
# 設置容器的對齊方式
container_layout.setAlignment(Qt.AlignCenter)
# 將容器添加到標題布局中
title_layout.addWidget(title_container)
layout.addLayout(title_layout)
# 設備列表
self.device_list_widget = QListWidget(self)
layout.addWidget(self.device_list_widget)
# 按鈕區域
button_layout = QHBoxLayout()
refresh_button = QPushButton("Refresh")
refresh_button.clicked.connect(self.parent.refresh_devices)
refresh_button.setStyleSheet(BUTTON_STYLE)
button_layout.addWidget(refresh_button)
done_button = QPushButton("Done")
done_button.setStyleSheet(BUTTON_STYLE)
done_button.clicked.connect(self.parent.hide_device_popup)
button_layout.addWidget(done_button)
layout.addLayout(button_layout)

1143
src/views/mainWindows.py Normal file

File diff suppressed because it is too large Load Diff

BIN
test_images/fire2.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

BIN
test_images/fire4.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
test_images/fire5.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
test_images/nofire1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

35
update_diary.md Normal file
View File

@ -0,0 +1,35 @@
## 20250204
Times: 5 Hours
### 完成:'
1. 串接 python script 和 主程式
### 尚未完成 / bug:
1. 主程式傳遞 python script 需要的資料
## 20250205
Times: 7 Hours
### 完成:
1. 添加 call python script 的 workflow
2. 修改目前的格式標準
### 尚未完成 / bug:
1. 開啟相機後上傳資料會出現 crush -> 將相機啟動的時間改為選擇模式且該模式 input 需要鏡頭 (input_format: Thread?)
2. script 端需要修正傳入需要處理的資料 -> 分解 param
3. 將結果顯示在 APP 中 而不是 terminal
4. 目前還沒有 bounding box 的 script 所以沒辦法嘗試相關的資料, 可以先寫一個簡單回傳 [(a,b), (c,d)] 的 sample code 進行 output 的 UI 串接和開發 (需要訂下bounding box 的 output format and parameter)
5. 處理不同的 dongle 需要使用不同的 fw (偵測不同的資料夾)
## 20250206
Times: 8.5 Hours
### 完成事項
1. 將視訊鏡頭啟動時間修改成使用者選擇需要使用視訊鏡頭的模式
2. 解決 once mode 在沒開啟鏡頭時沒辦法傳遞資料給 python script -> 將上傳的資料加入 frame 佇列 (相關細節在 select tool中)
3. 修正 main app 傳遞的資料內容
4. 添加 dongle 型號的辨認 -> 根據 configs.json 使用不同的 FW 對應到不同的 dongle, device box 中的圖片也是
5. 添加 inference output 的 message box -> 之後要改成 Figma 中的 UI 樣式
### 尚未完成 / bug:
1. 增加錄音的功能處理
2. 增加不同 input format for python script -> 目前是用 numpy 的方式
3. 修改 popup windows 中顯示的 dongle 型號 -> 使用類似 完成事項4 的方式使用之前的 mapping
4. 修改 inference output format including bb and single model
5. multi-dongle inference

BIN
uxui/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white" stroke-opacity="0.3"/>
<circle cx="20" cy="20" r="10" stroke="white" stroke-opacity="0.3" stroke-width="2"/>
<circle cx="20" cy="20" r="4" fill="white" fill-opacity="0.3"/>
</svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white" stroke-opacity="0.3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.1 29.2475V32.0714C19.1 32.5845 19.5027 33 20 33C20.4973 33 20.9 32.5845 20.9 32.0714V29.2475C25.489 28.8551 29 25.5076 29 21.8573C29 21.3442 28.5973 20.9287 28.1 20.9287C27.6027 20.9287 27.2 21.3442 27.2 21.8573C27.2 24.8914 23.9217 27.4287 20 27.4287C16.0783 27.4287 12.8 24.8914 12.8 21.8573C12.8 21.3442 12.3973 20.9287 11.9 20.9287C11.4027 20.9287 11 21.3442 11 21.8573C11 25.5076 14.511 28.8552 19.1 29.2475ZM14.6 12.0737V20.4643C14.6 23.2546 16.9951 25.5715 20 25.5715C23.0049 25.5715 25.4 23.2548 25.4 20.4643V12.1072C25.4 9.31692 23.0049 7 20 7C17.0062 7 14.619 9.2985 14.6 12.0737ZM16.4 12.0853C16.4135 10.2734 18.0459 8.85744 20 8.85744C21.962 8.85744 23.6 10.2851 23.6 12.1076V20.4646C23.6 22.2869 21.962 23.7147 20 23.7147C18.038 23.7147 16.4 22.2871 16.4 20.4646V12.0853Z" fill="white" fill-opacity="0.3"/>
<path d="M19.6 29.2475V28.7884L19.1426 28.7493C14.7354 28.3726 11.5 25.1775 11.5 21.8573C11.5 21.6055 11.6935 21.4287 11.9 21.4287C12.1065 21.4287 12.3 21.6055 12.3 21.8573C12.3 23.5645 13.2223 25.0919 14.6234 26.1762C16.0255 27.2612 17.9345 27.9287 20 27.9287C22.0655 27.9287 23.9745 27.2612 25.3766 26.1762C26.7777 25.092 27.7 23.5645 27.7 21.8573C27.7 21.6055 27.8935 21.4287 28.1 21.4287C28.3065 21.4287 28.5 21.6055 28.5 21.8573C28.5 25.1774 25.2646 28.3725 20.8574 28.7493L20.4 28.7884V29.2475V32.0714C20.4 32.3232 20.2065 32.5 20 32.5C19.7935 32.5 19.6 32.3232 19.6 32.0714V29.2475ZM15.9 12.0815H15.9V12.0853V20.4646C15.9 22.6149 17.8165 24.2147 20 24.2147C22.1835 24.2147 24.1 22.6147 24.1 20.4646V12.1076C24.1 9.95728 22.1835 8.35744 20 8.35744C17.825 8.35744 15.9159 9.94408 15.9 12.0815ZM15.1 20.4643V12.0754C15.1179 9.59799 17.2589 7.5 20 7.5C22.752 7.5 24.9 9.61575 24.9 12.1072V20.4643C24.9 22.9559 22.752 25.0715 20 25.0715C17.248 25.0715 15.1 22.9558 15.1 20.4643Z" stroke="white" stroke-opacity="0.3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M19.6 29.2475V28.7884L19.1426 28.7493C14.7354 28.3726 11.5 25.1775 11.5 21.8573C11.5 21.6055 11.6935 21.4287 11.9 21.4287C12.1065 21.4287 12.3 21.6055 12.3 21.8573C12.3 23.5645 13.2223 25.0919 14.6234 26.1762C16.0255 27.2612 17.9345 27.9287 20 27.9287C22.0655 27.9287 23.9745 27.2612 25.3766 26.1762C26.7777 25.092 27.7 23.5645 27.7 21.8573C27.7 21.6055 27.8935 21.4287 28.1 21.4287C28.3065 21.4287 28.5 21.6055 28.5 21.8573C28.5 25.1774 25.2646 28.3725 20.8574 28.7493L20.4 28.7884V29.2475V32.0714C20.4 32.3232 20.2065 32.5 20 32.5C19.7935 32.5 19.6 32.3232 19.6 32.0714V29.2475ZM15.9 12.0815H15.9V12.0853V20.4646C15.9 22.6149 17.8165 24.2147 20 24.2147C22.1835 24.2147 24.1 22.6147 24.1 20.4646V12.1076C24.1 9.95728 22.1835 8.35744 20 8.35744C17.825 8.35744 15.9159 9.94408 15.9 12.0815ZM15.1 20.4643V12.0754C15.1179 9.59799 17.2589 7.5 20 7.5C22.752 7.5 24.9 9.61575 24.9 12.1072V20.4643C24.9 22.9559 22.752 25.0715 20 25.0715C17.248 25.0715 15.1 22.9558 15.1 20.4643Z" fill="white" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white"/>
<path d="M19.6 29.2475V28.7884L19.1426 28.7493C14.7354 28.3726 11.5 25.1775 11.5 21.8573C11.5 21.6055 11.6935 21.4287 11.9 21.4287C12.1065 21.4287 12.3 21.6055 12.3 21.8573C12.3 23.5645 13.2223 25.0919 14.6234 26.1762C16.0255 27.2612 17.9345 27.9287 20 27.9287C22.0655 27.9287 23.9745 27.2612 25.3766 26.1762C26.7777 25.092 27.7 23.5645 27.7 21.8573C27.7 21.6055 27.8935 21.4287 28.1 21.4287C28.3065 21.4287 28.5 21.6055 28.5 21.8573C28.5 25.1774 25.2646 28.3725 20.8574 28.7493L20.4 28.7884V29.2475V32.0714C20.4 32.3232 20.2065 32.5 20 32.5C19.7935 32.5 19.6 32.3232 19.6 32.0714V29.2475ZM15.9 12.0815H15.9V12.0853V20.4646C15.9 22.6149 17.8165 24.2147 20 24.2147C22.1835 24.2147 24.1 22.6147 24.1 20.4646V12.1076C24.1 9.95728 22.1835 8.35744 20 8.35744C17.825 8.35744 15.9159 9.94408 15.9 12.0815ZM15.1 20.4643V12.0754C15.1179 9.59799 17.2589 7.5 20 7.5C22.752 7.5 24.9 9.61575 24.9 12.1072V20.4643C24.9 22.9559 22.752 25.0715 20 25.0715C17.248 25.0715 15.1 22.9558 15.1 20.4643Z" fill="white" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="white" stroke="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.1 29.2475V32.0714C19.1 32.5845 19.5027 33 20 33C20.4973 33 20.9 32.5845 20.9 32.0714V29.2475C25.489 28.8551 29 25.5076 29 21.8573C29 21.3442 28.5973 20.9287 28.1 20.9287C27.6027 20.9287 27.2 21.3442 27.2 21.8573C27.2 24.8914 23.9217 27.4287 20 27.4287C16.0783 27.4287 12.8 24.8914 12.8 21.8573C12.8 21.3442 12.3973 20.9287 11.9 20.9287C11.4027 20.9287 11 21.3442 11 21.8573C11 25.5076 14.511 28.8552 19.1 29.2475ZM14.6 12.0737V20.4643C14.6 23.2546 16.9951 25.5715 20 25.5715C23.0049 25.5715 25.4 23.2548 25.4 20.4643V12.1072C25.4 9.31692 23.0049 7 20 7C17.0062 7 14.619 9.2985 14.6 12.0737ZM16.4 12.0853C16.4135 10.2734 18.0459 8.85744 20 8.85744C21.962 8.85744 23.6 10.2851 23.6 12.1076V20.4646C23.6 22.2869 21.962 23.7147 20 23.7147C18.038 23.7147 16.4 22.2871 16.4 20.4646V12.0853Z" fill="#005ED7" stroke="#005ED7" stroke-width="0.4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" fill="white" fill-opacity="0.5" stroke="white"/>
<rect x="12" y="12" width="16" height="16" rx="3" fill="#BA131D"/>
</svg>

After

Width:  |  Height:  |  Size: 274 B

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" stroke="white"/>
<rect x="12" y="12" width="16" height="16" rx="3" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 240 B

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" fill="white" stroke="white"/>
<rect x="12" y="12" width="16" height="16" rx="3" fill="#BA131D"/>
</svg>

After

Width:  |  Height:  |  Size: 255 B

View File

@ -0,0 +1,8 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white" stroke-opacity="0.3"/>
<path d="M15.7838 8C16.4555 8 17 8.54452 17 9.21622C17 9.88791 16.4555 10.4324 15.7838 10.4324H11.6486C10.977 10.4324 10.4324 10.977 10.4324 11.6486V15.7838C10.4324 16.4555 9.88791 17 9.21622 17C8.54452 17 8 16.4555 8 15.7838V11.6486C8 9.63355 9.63355 8 11.6486 8H15.7838Z" fill="white" fill-opacity="0.3"/>
<path d="M32 15.7838C32 16.4555 31.4555 17 30.7838 17C30.1121 17 29.5676 16.4555 29.5676 15.7838L29.5676 11.6486C29.5676 10.977 29.023 10.4324 28.3514 10.4324L24.2162 10.4324C23.5445 10.4324 23 9.88791 23 9.21622C23 8.54452 23.5445 8 24.2162 8L28.3514 8C30.3664 8 32 9.63355 32 11.6486L32 15.7838Z" fill="white" fill-opacity="0.3"/>
<circle cx="19.9999" cy="19.9999" r="3.69231" fill="white" fill-opacity="0.3"/>
<path d="M24.2162 32C23.5445 32 23 31.4555 23 30.7838C23 30.1121 23.5445 29.5676 24.2162 29.5676L28.3514 29.5676C29.023 29.5676 29.5676 29.023 29.5676 28.3514L29.5676 24.2162C29.5676 23.5445 30.1121 23 30.7838 23C31.4555 23 32 23.5445 32 24.2162L32 28.3514C32 30.3664 30.3664 32 28.3514 32L24.2162 32Z" fill="white" fill-opacity="0.3"/>
<path d="M8 24.2162C8 23.5445 8.54452 23 9.21622 23C9.88792 23 10.4324 23.5445 10.4324 24.2162L10.4324 28.3514C10.4324 29.023 10.977 29.5676 11.6486 29.5676L15.7838 29.5676C16.4555 29.5676 17 30.1121 17 30.7838C17 31.4555 16.4555 32 15.7838 32L11.6486 32C9.63355 32 8 30.3664 8 28.3514L8 24.2162Z" fill="white" fill-opacity="0.3"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,8 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M15.7838 8C16.4555 8 17 8.54452 17 9.21622C17 9.88791 16.4555 10.4324 15.7838 10.4324H11.6486C10.977 10.4324 10.4324 10.977 10.4324 11.6486V15.7838C10.4324 16.4555 9.88791 17 9.21622 17C8.54452 17 8 16.4555 8 15.7838V11.6486C8 9.63355 9.63355 8 11.6486 8H15.7838Z" fill="white"/>
<path d="M32 15.7838C32 16.4555 31.4555 17 30.7838 17C30.1121 17 29.5676 16.4555 29.5676 15.7838L29.5676 11.6486C29.5676 10.977 29.023 10.4324 28.3514 10.4324L24.2162 10.4324C23.5445 10.4324 23 9.88791 23 9.21622C23 8.54452 23.5445 8 24.2162 8L28.3514 8C30.3664 8 32 9.63355 32 11.6486L32 15.7838Z" fill="white"/>
<circle cx="19.9999" cy="19.9999" r="3.69231" fill="white"/>
<path d="M24.2162 32C23.5445 32 23 31.4555 23 30.7838C23 30.1121 23.5445 29.5676 24.2162 29.5676L28.3514 29.5676C29.023 29.5676 29.5676 29.023 29.5676 28.3514L29.5676 24.2162C29.5676 23.5445 30.1121 23 30.7838 23C31.4555 23 32 23.5445 32 24.2162L32 28.3514C32 30.3664 30.3664 32 28.3514 32L24.2162 32Z" fill="white"/>
<path d="M8 24.2162C8 23.5445 8.54452 23 9.21622 23C9.88792 23 10.4324 23.5445 10.4324 24.2162L10.4324 28.3514C10.4324 29.023 10.977 29.5676 11.6486 29.5676L15.7838 29.5676C16.4555 29.5676 17 30.1121 17 30.7838C17 31.4555 16.4555 32 15.7838 32L11.6486 32C9.63355 32 8 30.3664 8 28.3514L8 24.2162Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,8 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white"/>
<path d="M15.7838 8C16.4555 8 17 8.54452 17 9.21622C17 9.88791 16.4555 10.4324 15.7838 10.4324H11.6486C10.977 10.4324 10.4324 10.977 10.4324 11.6486V15.7838C10.4324 16.4555 9.88791 17 9.21622 17C8.54452 17 8 16.4555 8 15.7838V11.6486C8 9.63355 9.63355 8 11.6486 8H15.7838Z" fill="white"/>
<path d="M32 15.7838C32 16.4555 31.4555 17 30.7838 17C30.1121 17 29.5676 16.4555 29.5676 15.7838L29.5676 11.6486C29.5676 10.977 29.023 10.4324 28.3514 10.4324L24.2162 10.4324C23.5445 10.4324 23 9.88791 23 9.21622C23 8.54452 23.5445 8 24.2162 8L28.3514 8C30.3664 8 32 9.63355 32 11.6486L32 15.7838Z" fill="white"/>
<circle cx="19.9999" cy="19.9999" r="3.69231" fill="white"/>
<path d="M24.2162 32C23.5445 32 23 31.4555 23 30.7838C23 30.1121 23.5445 29.5676 24.2162 29.5676L28.3514 29.5676C29.023 29.5676 29.5676 29.023 29.5676 28.3514L29.5676 24.2162C29.5676 23.5445 30.1121 23 30.7838 23C31.4555 23 32 23.5445 32 24.2162L32 28.3514C32 30.3664 30.3664 32 28.3514 32L24.2162 32Z" fill="white"/>
<path d="M8 24.2162C8 23.5445 8.54452 23 9.21622 23C9.88792 23 10.4324 23.5445 10.4324 24.2162L10.4324 28.3514C10.4324 29.023 10.977 29.5676 11.6486 29.5676L15.7838 29.5676C16.4555 29.5676 17 30.1121 17 30.7838C17 31.4555 16.4555 32 15.7838 32L11.6486 32C9.63355 32 8 30.3664 8 28.3514L8 24.2162Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,8 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="white" stroke="white"/>
<path d="M15.7838 8C16.4555 8 17 8.54452 17 9.21622C17 9.88791 16.4555 10.4324 15.7838 10.4324H11.6486C10.977 10.4324 10.4324 10.977 10.4324 11.6486V15.7838C10.4324 16.4555 9.88791 17 9.21622 17C8.54452 17 8 16.4555 8 15.7838V11.6486C8 9.63355 9.63355 8 11.6486 8H15.7838Z" fill="#005ED7"/>
<path d="M32 15.7838C32 16.4555 31.4555 17 30.7838 17C30.1121 17 29.5676 16.4555 29.5676 15.7838L29.5676 11.6486C29.5676 10.977 29.023 10.4324 28.3514 10.4324L24.2162 10.4324C23.5445 10.4324 23 9.88791 23 9.21622C23 8.54452 23.5445 8 24.2162 8L28.3514 8C30.3664 8 32 9.63355 32 11.6486L32 15.7838Z" fill="#005ED7"/>
<circle cx="19.9999" cy="19.9999" r="3.69231" fill="#005ED7"/>
<path d="M24.2162 32C23.5445 32 23 31.4555 23 30.7838C23 30.1121 23.5445 29.5676 24.2162 29.5676L28.3514 29.5676C29.023 29.5676 29.5676 29.023 29.5676 28.3514L29.5676 24.2162C29.5676 23.5445 30.1121 23 30.7838 23C31.4555 23 32 23.5445 32 24.2162L32 28.3514C32 30.3664 30.3664 32 28.3514 32L24.2162 32Z" fill="#005ED7"/>
<path d="M8 24.2162C8 23.5445 8.54452 23 9.21622 23C9.88792 23 10.4324 23.5445 10.4324 24.2162L10.4324 28.3514C10.4324 29.023 10.977 29.5676 11.6486 29.5676L15.7838 29.5676C16.4555 29.5676 17 30.1121 17 30.7838C17 31.4555 16.4555 32 15.7838 32L11.6486 32C9.63355 32 8 30.3664 8 28.3514L8 24.2162Z" fill="#005ED7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white" stroke-opacity="0.3"/>
<path d="M15.9654 13.1611C15.6306 12.8079 15.6306 12.2356 15.9654 11.8823L19.394 8.26495C19.7288 7.91168 20.2712 7.91168 20.606 8.26495L24.0346 11.8823C24.3694 12.2356 24.3694 12.8079 24.0346 13.1611C23.8672 13.3378 23.6479 13.4261 23.4286 13.4261C23.2093 13.4261 22.99 13.3378 22.8225 13.1611L20.8571 11.0875V25.6696C20.8571 26.1694 20.4734 26.5739 20 26.5739C19.5266 26.5739 19.1429 26.1694 19.1429 25.6696V11.0875L17.1775 13.1611C16.8426 13.5144 16.3002 13.5144 15.9654 13.1611ZM31.1429 22.0522C30.6691 22.0522 30.2857 22.4567 30.2857 22.9565V27.4783C30.2857 28.9743 29.1323 30.1913 27.7143 30.1913H12.2857C10.8677 30.1913 9.71429 28.9743 9.71429 27.4783V22.9565C9.71429 22.4567 9.3305 22.0522 8.85714 22.0522C8.38379 22.0522 8 22.4567 8 22.9565V27.4783C8 29.9714 9.92271 32 12.2857 32H27.7143C30.0773 32 32 29.9714 32 27.4783V22.9565C32 22.4567 31.6166 22.0522 31.1429 22.0522Z" fill="white" fill-opacity="0.3"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M15.9654 13.1611C15.6306 12.8079 15.6306 12.2356 15.9654 11.8823L19.394 8.26495C19.7288 7.91168 20.2712 7.91168 20.606 8.26495L24.0346 11.8823C24.3694 12.2356 24.3694 12.8079 24.0346 13.1611C23.8672 13.3378 23.6479 13.4261 23.4286 13.4261C23.2093 13.4261 22.99 13.3378 22.8225 13.1611L20.8571 11.0875V25.6696C20.8571 26.1694 20.4734 26.5739 20 26.5739C19.5266 26.5739 19.1429 26.1694 19.1429 25.6696V11.0875L17.1775 13.1611C16.8426 13.5144 16.3002 13.5144 15.9654 13.1611ZM31.1429 22.0522C30.6691 22.0522 30.2857 22.4567 30.2857 22.9565V27.4783C30.2857 28.9743 29.1323 30.1913 27.7143 30.1913H12.2857C10.8677 30.1913 9.71429 28.9743 9.71429 27.4783V22.9565C9.71429 22.4567 9.3305 22.0522 8.85714 22.0522C8.38379 22.0522 8 22.4567 8 22.9565V27.4783C8 29.9714 9.92271 32 12.2857 32H27.7143C30.0773 32 32 29.9714 32 27.4783V22.9565C32 22.4567 31.6166 22.0522 31.1429 22.0522Z" fill="white" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white"/>
<path d="M15.9654 13.1611C15.6306 12.8079 15.6306 12.2356 15.9654 11.8823L19.394 8.26495C19.7288 7.91168 20.2712 7.91168 20.606 8.26495L24.0346 11.8823C24.3694 12.2356 24.3694 12.8079 24.0346 13.1611C23.8672 13.3378 23.6479 13.4261 23.4286 13.4261C23.2093 13.4261 22.99 13.3378 22.8225 13.1611L20.8571 11.0875V25.6696C20.8571 26.1694 20.4734 26.5739 20 26.5739C19.5266 26.5739 19.1429 26.1694 19.1429 25.6696V11.0875L17.1775 13.1611C16.8426 13.5144 16.3002 13.5144 15.9654 13.1611ZM31.1429 22.0522C30.6691 22.0522 30.2857 22.4567 30.2857 22.9565V27.4783C30.2857 28.9743 29.1323 30.1913 27.7143 30.1913H12.2857C10.8677 30.1913 9.71429 28.9743 9.71429 27.4783V22.9565C9.71429 22.4567 9.3305 22.0522 8.85714 22.0522C8.38379 22.0522 8 22.4567 8 22.9565V27.4783C8 29.9714 9.92271 32 12.2857 32H27.7143C30.0773 32 32 29.9714 32 27.4783V22.9565C32 22.4567 31.6166 22.0522 31.1429 22.0522Z" fill="white" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="white" stroke="white"/>
<path d="M15.9654 13.1611C15.6306 12.8079 15.6306 12.2356 15.9654 11.8823L19.394 8.26495C19.7288 7.91168 20.2712 7.91168 20.606 8.26495L24.0346 11.8823C24.3694 12.2356 24.3694 12.8079 24.0346 13.1611C23.8672 13.3378 23.6479 13.4261 23.4286 13.4261C23.2093 13.4261 22.99 13.3378 22.8225 13.1611L20.8571 11.0875V25.6696C20.8571 26.1694 20.4734 26.5739 20 26.5739C19.5266 26.5739 19.1429 26.1694 19.1429 25.6696V11.0875L17.1775 13.1611C16.8426 13.5144 16.3002 13.5144 15.9654 13.1611ZM31.1429 22.0522C30.6691 22.0522 30.2857 22.4567 30.2857 22.9565V27.4783C30.2857 28.9743 29.1323 30.1913 27.7143 30.1913H12.2857C10.8677 30.1913 9.71429 28.9743 9.71429 27.4783V22.9565C9.71429 22.4567 9.3305 22.0522 8.85714 22.0522C8.38379 22.0522 8 22.4567 8 22.9565V27.4783C8 29.9714 9.92271 32 12.2857 32H27.7143C30.0773 32 32 29.9714 32 27.4783V22.9565C32 22.4567 31.6166 22.0522 31.1429 22.0522Z" fill="#005ED7" stroke="#005ED7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<circle cx="20" cy="20" r="10" stroke="white" stroke-width="2"/>
<circle cx="20" cy="20" r="4" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 318 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" stroke="white"/>
<circle cx="20" cy="20" r="10" stroke="white" stroke-width="2"/>
<circle cx="20" cy="20" r="4" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 284 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="white" stroke="white"/>
<circle cx="20" cy="20" r="11" stroke="#005ED7" stroke-width="2"/>
<circle cx="20" cy="20" r="4" fill="#005ED7"/>
</svg>

After

Width:  |  Height:  |  Size: 301 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M28 12.001L12 28.001" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
<path d="M28 28L12 12" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" stroke="#62FFF8"/>
<path d="M28 12.001L12 28.001" stroke="#62FFF8" stroke-width="1.5" stroke-linecap="round"/>
<path d="M28 28L12 12" stroke="#62FFF8" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 331 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" stroke="#62FFF8"/>
<path d="M28 12.001L12 28.001" stroke="#143058" stroke-width="1.5" stroke-linecap="round"/>
<path d="M28 28L12 12" stroke="#143058" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 346 B

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M16.6378 14.301C16.3588 14.0066 16.3588 13.5297 16.6378 13.2353L19.495 10.2208C19.774 9.9264 20.226 9.9264 20.505 10.2208L23.3622 13.2353C23.6412 13.5297 23.6412 14.0066 23.3622 14.301C23.2227 14.4481 23.0399 14.5217 22.8571 14.5217C22.6744 14.5217 22.4916 14.4481 22.3521 14.301L20.7143 12.5729V24.7246C20.7143 25.1412 20.3945 25.4783 20 25.4783C19.6055 25.4783 19.2857 25.1412 19.2857 24.7246V12.5729L17.6479 14.301C17.3689 14.5953 16.9169 14.5953 16.6378 14.301ZM29.2857 21.7101C28.8909 21.7101 28.5714 22.0472 28.5714 22.4638V26.2319C28.5714 27.4786 27.6102 28.4928 26.4286 28.4928H13.5714C12.3898 28.4928 11.4286 27.4786 11.4286 26.2319V22.4638C11.4286 22.0472 11.1087 21.7101 10.7143 21.7101C10.3198 21.7101 10 22.0472 10 22.4638V26.2319C10 28.3095 11.6023 30 13.5714 30H26.4286C28.3977 30 30 28.3095 30 26.2319V22.4638C30 22.0472 29.6805 21.7101 29.2857 21.7101Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" stroke="#62FFF8"/>
<path d="M16.6378 14.301C16.3588 14.0066 16.3588 13.5297 16.6378 13.2353L19.495 10.2208C19.774 9.9264 20.226 9.9264 20.505 10.2208L23.3622 13.2353C23.6412 13.5297 23.6412 14.0066 23.3622 14.301C23.2227 14.4481 23.0399 14.5217 22.8571 14.5217C22.6744 14.5217 22.4916 14.4481 22.3521 14.301L20.7143 12.5729V24.7246C20.7143 25.1412 20.3945 25.4783 20 25.4783C19.6055 25.4783 19.2857 25.1412 19.2857 24.7246V12.5729L17.6479 14.301C17.3689 14.5953 16.9169 14.5953 16.6378 14.301ZM29.2857 21.7101C28.8909 21.7101 28.5714 22.0472 28.5714 22.4638V26.2319C28.5714 27.4786 27.6102 28.4928 26.4286 28.4928H13.5714C12.3898 28.4928 11.4286 27.4786 11.4286 26.2319V22.4638C11.4286 22.0472 11.1087 21.7101 10.7143 21.7101C10.3198 21.7101 10 22.0472 10 22.4638V26.2319C10 28.3095 11.6023 30 13.5714 30H26.4286C28.3977 30 30 28.3095 30 26.2319V22.4638C30 22.0472 29.6805 21.7101 29.2857 21.7101Z" fill="#62FFF8"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" stroke="#62FFF8"/>
<path d="M16.6378 14.301C16.3588 14.0066 16.3588 13.5297 16.6378 13.2353L19.495 10.2208C19.774 9.9264 20.226 9.9264 20.505 10.2208L23.3622 13.2353C23.6412 13.5297 23.6412 14.0066 23.3622 14.301C23.2227 14.4481 23.0399 14.5217 22.8571 14.5217C22.6744 14.5217 22.4916 14.4481 22.3521 14.301L20.7143 12.5729V24.7246C20.7143 25.1412 20.3945 25.4783 20 25.4783C19.6055 25.4783 19.2857 25.1412 19.2857 24.7246V12.5729L17.6479 14.301C17.3689 14.5953 16.9169 14.5953 16.6378 14.301ZM29.2857 21.7101C28.8909 21.7101 28.5714 22.0472 28.5714 22.4638V26.2319C28.5714 27.4786 27.6102 28.4928 26.4286 28.4928H13.5714C12.3898 28.4928 11.4286 27.4786 11.4286 26.2319V22.4638C11.4286 22.0472 11.1087 21.7101 10.7143 21.7101C10.3198 21.7101 10 22.0472 10 22.4638V26.2319C10 28.3095 11.6023 30 13.5714 30H26.4286C28.3977 30 30 28.3095 30 26.2319V22.4638C30 22.0472 29.6805 21.7101 29.2857 21.7101Z" fill="#143058"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8822 15.5307C18.5737 15.8393 18.0734 15.8393 17.7649 15.5307C17.4563 15.2221 17.4563 14.7219 17.7649 14.4133L20.5583 11.6199C22.7182 9.46003 26.22 9.46003 28.3799 11.6199C30.5398 13.7798 30.5398 17.2816 28.3799 19.4415L25.5865 22.2349C25.2779 22.5435 24.7776 22.5435 24.469 22.2349C24.1605 21.9264 24.1605 21.4261 24.469 21.1175L27.2625 18.3241C28.8053 16.7814 28.8053 14.28 27.2625 12.7373C25.7198 11.1945 23.2184 11.1945 21.6756 12.7373L18.8822 15.5307ZM12.7371 12.7371C13.0457 12.4286 13.5459 12.4286 13.8545 12.7371L27.263 26.1456C27.5715 26.4541 27.5715 26.9544 27.263 27.263C26.9544 27.5715 26.4541 27.5715 26.1456 27.263L12.7371 13.8545C12.4286 13.5459 12.4286 13.0457 12.7371 12.7371ZM15.5307 18.883C15.8393 18.5745 15.8393 18.0742 15.5307 17.7657C15.2222 17.4571 14.7219 17.4571 14.4133 17.7657L11.6199 20.5591C9.46003 22.719 9.46003 26.2208 11.6199 28.3807C13.7798 30.5406 17.2816 30.5406 19.4415 28.3807L22.2349 25.5873C22.5434 25.2787 22.5434 24.7785 22.2349 24.4699C21.9264 24.1613 21.4261 24.1613 21.1176 24.4699L18.3242 27.2633C16.7814 28.8061 14.28 28.8061 12.7373 27.2633C11.1945 25.7206 11.1945 23.2192 12.7373 21.6764L15.5307 18.883Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" stroke="#62FFF8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8822 15.5307C18.5737 15.8393 18.0734 15.8393 17.7649 15.5307C17.4563 15.2221 17.4563 14.7219 17.7649 14.4133L20.5583 11.6199C22.7182 9.46003 26.22 9.46003 28.3799 11.6199C30.5398 13.7798 30.5398 17.2816 28.3799 19.4415L25.5865 22.2349C25.2779 22.5435 24.7776 22.5435 24.469 22.2349C24.1605 21.9264 24.1605 21.4261 24.469 21.1175L27.2625 18.3241C28.8053 16.7814 28.8053 14.28 27.2625 12.7373C25.7198 11.1945 23.2184 11.1945 21.6756 12.7373L18.8822 15.5307ZM12.7371 12.7371C13.0457 12.4286 13.5459 12.4286 13.8545 12.7371L27.263 26.1456C27.5715 26.4541 27.5715 26.9544 27.263 27.263C26.9544 27.5715 26.4541 27.5715 26.1456 27.263L12.7371 13.8545C12.4286 13.5459 12.4286 13.0457 12.7371 12.7371ZM15.5307 18.883C15.8393 18.5745 15.8393 18.0742 15.5307 17.7657C15.2222 17.4571 14.7219 17.4571 14.4133 17.7657L11.6199 20.5591C9.46003 22.719 9.46003 26.2208 11.6199 28.3807C13.7798 30.5406 17.2816 30.5406 19.4415 28.3807L22.2349 25.5873C22.5434 25.2787 22.5434 24.7785 22.2349 24.4699C21.9264 24.1613 21.4261 24.1613 21.1176 24.4699L18.3242 27.2633C16.7814 28.8061 14.28 28.8061 12.7373 27.2633C11.1945 25.7206 11.1945 23.2192 12.7373 21.6764L15.5307 18.883Z" fill="#62FFF8"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="19.5" fill="#62FFF8" stroke="#62FFF8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8822 15.5307C18.5737 15.8393 18.0734 15.8393 17.7649 15.5307C17.4563 15.2221 17.4563 14.7219 17.7649 14.4133L20.5583 11.6199C22.7182 9.46003 26.22 9.46003 28.3799 11.6199C30.5398 13.7798 30.5398 17.2816 28.3799 19.4415L25.5865 22.2349C25.2779 22.5435 24.7776 22.5435 24.469 22.2349C24.1605 21.9264 24.1605 21.4261 24.469 21.1175L27.2625 18.3241C28.8053 16.7814 28.8053 14.28 27.2625 12.7373C25.7198 11.1945 23.2184 11.1945 21.6756 12.7373L18.8822 15.5307ZM12.7371 12.7371C13.0457 12.4286 13.5459 12.4286 13.8545 12.7371L27.263 26.1456C27.5715 26.4541 27.5715 26.9544 27.263 27.263C26.9544 27.5715 26.4541 27.5715 26.1456 27.263L12.7371 13.8545C12.4286 13.5459 12.4286 13.0457 12.7371 12.7371ZM15.5307 18.883C15.8393 18.5745 15.8393 18.0742 15.5307 17.7657C15.2222 17.4571 14.7219 17.4571 14.4133 17.7657L11.6199 20.5591C9.46003 22.719 9.46003 26.2208 11.6199 28.3807C13.7798 30.5406 17.2816 30.5406 19.4415 28.3807L22.2349 25.5873C22.5434 25.2787 22.5434 24.7785 22.2349 24.4699C21.9264 24.1613 21.4261 24.1613 21.1176 24.4699L18.3242 27.2633C16.7814 28.8061 14.28 28.8061 12.7373 27.2633C11.1945 25.7206 11.1945 23.2192 12.7373 21.6764L15.5307 18.883Z" fill="#143058"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M29.9998 14.878L25.1218 10L21.7417 13.3801L26.6197 18.2581L29.9998 14.878Z" fill="white"/>
<path d="M10 29.9999L15.3659 29.5122L24.5996 20.2785L19.7215 15.4004L10.4878 24.6341L10 29.9999Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 422 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" stroke="#62FFF8"/>
<path d="M29.9998 14.878L25.1218 10L21.7417 13.3801L26.6197 18.2581L29.9998 14.878Z" fill="#62FFF8"/>
<path d="M10 29.9999L15.3659 29.5122L24.5996 20.2785L19.7215 15.4004L10.4878 24.6341L10 29.9999Z" fill="#62FFF8"/>
</svg>

After

Width:  |  Height:  |  Size: 394 B

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="39" height="39" rx="19.5" fill="#62FFF8" stroke="#62FFF8"/>
<path d="M29.9998 14.878L25.1218 10L21.7417 13.3801L26.6197 18.2581L29.9998 14.878Z" fill="#143058"/>
<path d="M10 29.9999L15.3659 29.5122L24.5996 20.2785L19.7215 15.4004L10.4878 24.6341L10 29.9999Z" fill="#143058"/>
</svg>

After

Width:  |  Height:  |  Size: 409 B

View File

@ -0,0 +1,18 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_168_1748)">
<circle cx="16" cy="12" r="11.5" fill="#62FFF8" fill-opacity="0.3" stroke="white"/>
<path d="M20.6225 6.64664L16.0003 11.287L11.378 6.64664C11.2556 6.53626 11.118 6.48106 10.9654 6.48106C10.8128 6.48106 10.6782 6.5394 10.5616 6.65607C10.445 6.77274 10.3869 6.90788 10.3873 7.06148C10.3877 7.21508 10.4426 7.35316 10.5522 7.47573L15.1745 12.1161L10.5522 16.7565C10.3933 16.916 10.3413 17.1063 10.3961 17.3275C10.4509 17.5486 10.5855 17.6867 10.7999 17.7417C11.0143 17.7967 11.2068 17.7445 11.3775 17.585L15.9997 12.9446L20.622 17.585C20.7444 17.6954 20.882 17.7506 21.0346 17.7506C21.1872 17.7506 21.3218 17.6922 21.4384 17.5755C21.555 17.4589 21.6131 17.3237 21.6127 17.1701C21.6123 17.0165 21.5574 16.8785 21.4478 16.7559L16.8255 12.1155L21.4478 7.47514C21.6067 7.31564 21.6587 7.12532 21.6039 6.90415C21.5491 6.68298 21.4116 6.5449 21.1913 6.4899C20.971 6.43491 20.7814 6.48715 20.6225 6.64664Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_168_1748" x="0" y="0" width="32" height="32" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_168_1748"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_168_1748" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,18 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_153_1435)">
<circle cx="16" cy="12" r="11.5" stroke="white"/>
<path d="M20.6225 6.64664L16.0003 11.287L11.378 6.64664C11.2556 6.53626 11.118 6.48106 10.9654 6.48106C10.8128 6.48106 10.6782 6.5394 10.5616 6.65607C10.445 6.77274 10.3869 6.90788 10.3873 7.06148C10.3877 7.21508 10.4426 7.35316 10.5522 7.47573L15.1745 12.1161L10.5522 16.7565C10.3933 16.916 10.3413 17.1063 10.3961 17.3275C10.4509 17.5486 10.5855 17.6867 10.7999 17.7417C11.0143 17.7967 11.2068 17.7445 11.3775 17.585L15.9997 12.9446L20.622 17.585C20.7444 17.6954 20.882 17.7506 21.0346 17.7506C21.1872 17.7506 21.3218 17.6922 21.4384 17.5755C21.555 17.4589 21.6131 17.3237 21.6127 17.1701C21.6123 17.0165 21.5574 16.8785 21.4478 16.7559L16.8255 12.1155L21.4478 7.47514C21.6067 7.31564 21.6587 7.12532 21.6039 6.90415C21.5491 6.68298 21.4116 6.5449 21.1913 6.4899C20.971 6.43491 20.7814 6.48715 20.6225 6.64664Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_153_1435" x="0" y="0" width="32" height="32" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_153_1435"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_153_1435" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,18 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_168_1749)">
<circle cx="16" cy="12" r="11.5" fill="white" stroke="white"/>
<path d="M20.6225 6.64664L16.0003 11.287L11.378 6.64664C11.2556 6.53626 11.118 6.48106 10.9654 6.48106C10.8128 6.48106 10.6782 6.5394 10.5616 6.65607C10.445 6.77274 10.3869 6.90788 10.3873 7.06148C10.3877 7.21508 10.4426 7.35316 10.5522 7.47573L15.1745 12.1161L10.5522 16.7565C10.3933 16.916 10.3413 17.1063 10.3961 17.3275C10.4509 17.5486 10.5855 17.6867 10.7999 17.7417C11.0143 17.7967 11.2068 17.7445 11.3775 17.585L15.9997 12.9446L20.622 17.585C20.7444 17.6954 20.882 17.7506 21.0346 17.7506C21.1872 17.7506 21.3218 17.6922 21.4384 17.5755C21.555 17.4589 21.6131 17.3237 21.6127 17.1701C21.6123 17.0165 21.5574 16.8785 21.4478 16.7559L16.8255 12.1155L21.4478 7.47514C21.6067 7.31564 21.6587 7.12532 21.6039 6.90415C21.5491 6.68298 21.4116 6.5449 21.1913 6.4899C20.971 6.43491 20.7814 6.48715 20.6225 6.64664Z" fill="#143058"/>
</g>
<defs>
<filter id="filter0_d_168_1749" x="0" y="0" width="32" height="32" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_168_1749"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_168_1749" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,3 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.8 11.2486H45C46.8 11.2486 48 13.0631 48 14.8776V39.676C48 41.4905 46.8 42.7002 45 42.7002H3C1.2 42.7002 0 41.4905 0 39.676V29.9986V29.3937V14.8776V6.40987C0 5.80503 0.6 5.2002 1.8 5.2002H17.4C18.6 5.2002 18.6 5.80503 19.2 6.40987L22.8 11.2486Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@ -0,0 +1,3 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.2965 36.6663C25.0739 36.6663 24.0742 35.5691 24.0742 34.2273V29.3493C24.0742 28.0075 25.0739 26.9102 26.2965 26.9102C27.519 26.9102 28.5187 28.0075 28.5187 29.3493V30.1623H35.1853C35.9999 30.1623 36.6668 30.8943 36.6668 31.7883C36.6668 32.6823 35.9999 33.4143 35.1853 33.4143H28.5187V34.2273C28.5187 35.5691 27.519 36.6663 26.2965 36.6663ZM19.6298 33.4143H4.81498C4.00046 33.4143 3.3335 32.6823 3.3335 31.7883C3.3335 30.8943 4.00046 30.1623 4.81498 30.1623H19.6298C20.4443 30.1623 21.1113 30.8943 21.1113 31.7883C21.1113 32.6823 20.4443 33.4143 19.6298 33.4143ZM13.7039 24.8777C12.4813 24.8777 11.4816 23.7805 11.4816 22.4387V21.6257H4.81498C4.00046 21.6257 3.3335 20.8937 3.3335 19.9997C3.3335 19.1057 4.00046 18.3737 4.81498 18.3737H11.4816V17.5607C11.4816 16.2189 12.4813 15.1216 13.7039 15.1216C14.9264 15.1216 15.9261 16.2189 15.9261 17.5607V22.4387C15.9261 23.7805 14.9264 24.8777 13.7039 24.8777ZM35.1853 21.6257H20.3705C19.556 21.6257 18.8891 20.8937 18.8891 19.9997C18.8891 19.1057 19.556 18.3737 20.3705 18.3737H35.1853C35.9999 18.3737 36.6668 19.1057 36.6668 19.9997C36.6668 20.8937 35.9999 21.6257 35.1853 21.6257ZM26.2965 13.0891C25.0739 13.0891 24.0742 11.9919 24.0742 10.6501V5.77203C24.0742 4.43024 25.0739 3.33301 26.2965 3.33301C27.519 3.33301 28.5187 4.43024 28.5187 5.77203V6.58504H35.1853C35.9999 6.58504 36.6668 7.31707 36.6668 8.21106C36.6668 9.10504 35.9999 9.83707 35.1853 9.83707H28.5187V10.6501C28.5187 11.9919 27.519 13.0891 26.2965 13.0891ZM19.6298 9.83707H4.81498C4.00046 9.83707 3.3335 9.10504 3.3335 8.21106C3.3335 7.31707 4.00046 6.58504 4.81498 6.58504H19.6298C20.4443 6.58504 21.1113 7.31707 21.1113 8.21106C21.1113 9.10504 20.4443 9.83707 19.6298 9.83707Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,3 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M37.2044 16.8491H34.1336H34.0975V19.2044H34.1336H37.2044C37.6422 19.2044 38 19.5622 38 20C38 20.4378 37.6422 20.7956 37.2044 20.7956H34.1336H34.0975V23.1509H34.1336H37.2044C37.6422 23.1509 38 23.5087 38 23.9465C38 24.3843 37.6422 24.7421 37.2044 24.7421H34.1336H34.0975V27.0974H34.1336H37.2044C37.6422 27.0974 38 27.4552 38 27.893C38 28.3308 37.6422 28.6886 37.2044 28.6886H34.1336H34.0975V32.1094C34.0975 33.2062 33.2078 34.0975 32.1093 34.0975H28.6886V34.1336V37.2044C28.6886 37.6422 28.3308 38 27.893 38C27.4552 38 27.0974 37.6422 27.0974 37.2044V34.1336V34.0975H24.7421V34.1336V37.2044C24.7421 37.6422 24.3843 38 23.9465 38C23.5087 38 23.1509 37.6422 23.1509 37.2044V34.1336V34.0975H20.7956V34.1336V37.2044C20.7956 37.6422 20.4378 38 20 38C19.5622 38 19.2044 37.6422 19.2044 37.2044V34.1336V34.0975H16.8491V34.1336V37.2044C16.8491 37.6422 16.4913 38 16.0535 38C15.6157 38 15.2579 37.6422 15.2579 37.2044V34.1336V34.0975H12.9026V34.1336V37.2044C12.9026 37.6422 12.5448 38 12.107 38C11.6692 38 11.3114 37.6422 11.3114 37.2044V34.1336V34.0975H7.89065C6.79383 34.0975 5.90252 33.2078 5.90252 32.1094V28.6886H5.86643H2.79558C2.35777 28.6886 2 28.3308 2 27.893C2 27.4552 2.3578 27.0974 2.79558 27.0974H5.86643H5.90252V24.7421H5.86643H2.79558C2.35777 24.7421 2 24.3843 2 23.9465C2 23.5087 2.3578 23.1509 2.79558 23.1509H5.86643H5.90252V20.7956H5.86643H2.79558C2.35777 20.7956 2 20.4378 2 20C2 19.5622 2.3578 19.2044 2.79558 19.2044H5.86643H5.90252V16.8491H5.86643H2.79558C2.35777 16.8491 2 16.4913 2 16.0535C2 15.6157 2.3578 15.2579 2.79558 15.2579H5.86643H5.90252V12.9026H5.86643H2.79558C2.35777 12.9026 2 12.5448 2 12.107C2 11.6692 2.3578 11.3114 2.79558 11.3114H5.86643H5.90252V7.89065C5.90252 6.79383 6.79223 5.90252 7.89065 5.90252H11.3114V5.86643V2.79558C11.3114 2.35777 11.6692 2 12.107 2C12.5448 2 12.9026 2.3578 12.9026 2.79558V5.86643V5.90252H15.2579V5.86643V2.79558C15.2579 2.35777 15.6157 2 16.0535 2C16.4913 2 16.8491 2.3578 16.8491 2.79558V5.86643V5.90252H19.2044V5.86643V2.79558C19.2044 2.35777 19.5622 2 20 2C20.4378 2 20.7956 2.3578 20.7956 2.79558V5.86643V5.90252H23.1509V5.86643V2.79558C23.1509 2.35777 23.5087 2 23.9465 2C24.3843 2 24.7421 2.3578 24.7421 2.79558V5.86643V5.90252H27.0974V5.86643V2.79558C27.0974 2.35777 27.4552 2 27.893 2C28.3308 2 28.6886 2.3578 28.6886 2.79558V5.86643V5.90252H32.1093C33.2062 5.90252 34.0975 6.79223 34.0975 7.89065V11.3114H34.1336H37.2044C37.6422 11.3114 38 11.6692 38 12.107C38 12.5448 37.6422 12.9026 37.2044 12.9026H34.1336H34.0975V15.2579H34.1336H37.2044C37.6422 15.2579 38 15.6157 38 16.0535C38 16.4913 37.6422 16.8491 37.2044 16.8491ZM11.0897 9.20255H28.9115V9.20064C29.9548 9.20064 30.8006 10.0464 30.8006 11.0896V28.9117C30.8006 29.9549 29.9548 30.8006 28.9115 30.8006H11.0897C10.0464 30.8006 9.20064 29.9549 9.20064 28.9117V11.0915C9.20064 10.0483 10.0464 9.20255 11.0897 9.20255ZM25.6196 24.6756V28.9117L25.6177 28.9156H28.9097V16.2759H24.6731C24.1533 16.2759 23.7285 15.8511 23.7285 15.3314C23.7285 14.8116 24.1533 14.3869 24.6731 14.3869H28.9097V11.0952H20.9433V15.3314C20.9433 15.581 20.8427 15.8176 20.6639 15.9964L15.9895 20.6704C15.8069 20.8548 15.5647 20.9498 15.3244 20.9498C15.0841 20.9498 14.8438 20.8548 14.6593 20.6704C14.2904 20.3034 14.2904 19.7035 14.6593 19.3347L19.0598 14.9346V11.0914H16.2746V15.3276C16.2746 15.8474 15.8498 16.2721 15.33 16.2721C14.8102 16.2721 14.3855 15.8473 14.3855 15.3276V11.0914H11.0935V23.7311H15.33C15.8498 23.7311 16.2746 24.1559 16.2746 24.6756C16.2746 25.1954 15.8498 25.6201 15.33 25.6201H11.0935V28.9118H19.0598V24.6756C19.0598 24.4632 19.1306 24.2546 19.2685 24.0851L23.0374 19.4111C23.3634 19.005 23.9577 18.9435 24.3638 19.2695C24.77 19.5955 24.8315 20.1897 24.5054 20.5959L20.9452 25.0109V28.9117H23.7304V24.6756C23.7304 24.1558 24.1552 23.7311 24.675 23.7311C25.1948 23.7311 25.6196 24.1558 25.6196 24.6756Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,4 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M139.201 99.6146L122.901 91.4647V98.7172C122.901 102.894 121.243 106.899 118.288 109.848C115.339 112.802 111.335 114.461 107.158 114.461H55.1273C55.1782 113.593 55.2041 112.718 55.2041 111.837C55.2041 109.15 54.9637 106.519 54.5033 103.965H107.158C108.548 103.965 109.887 103.414 110.868 102.427C111.854 101.446 112.405 100.108 112.405 98.7172V35.7434C112.405 34.3528 111.854 33.0146 110.868 32.0332C109.887 31.0466 108.548 30.4956 107.158 30.4956H23.1927C21.802 30.4956 20.4638 31.0466 19.4825 32.0332C18.4959 33.0146 17.9448 34.3528 17.9448 35.7434V68.2798C15.7213 67.9344 13.4428 67.7551 11.1225 67.7551C9.88548 67.7551 8.66041 67.806 7.44922 67.906V35.7434C7.44922 31.5662 9.10754 27.5621 12.0621 24.6128C15.0113 21.6583 19.0154 20 23.1927 20H107.158C111.335 20 115.339 21.6583 118.288 24.6128C121.243 27.5621 122.901 31.5662 122.901 35.7434V42.9959L139.201 34.8461C142.454 33.2193 146.317 33.3924 149.408 35.3079C152.504 37.2181 154.388 40.5976 154.388 44.2344V90.2263C154.388 93.863 152.504 97.2426 149.408 99.1528C146.317 101.068 142.454 101.241 139.201 99.6146ZM143.892 90.2263V44.2344L122.901 54.73V79.7306L143.892 90.2263ZM23.1927 51.4869C23.1927 42.7965 30.2457 35.7434 38.9361 35.7434C47.6265 35.7434 54.6795 42.7965 54.6795 51.4869C54.6795 60.1773 47.6265 67.2303 38.9361 67.2303C30.2457 67.2303 23.1927 60.1773 23.1927 51.4869ZM44.1839 51.4869C44.1839 48.5901 41.8329 46.2391 38.9361 46.2391C36.0393 46.2391 33.6883 48.5901 33.6883 51.4869C33.6883 54.3837 36.0393 56.7347 38.9361 56.7347C41.8329 56.7347 44.1839 54.3837 44.1839 51.4869Z" fill="white"/>
<path d="M34.5778 110.904L28.605 115.128C26.3161 116.702 25.2461 119.433 25.4493 122.15C24.9888 129.064 15.1697 128.123 15.8606 121.208C15.8606 115.72 18.5423 110.554 23.0524 107.366L29.0253 103.142C34.944 98.9993 31.9238 89.5829 24.6642 89.6096H22.1451C18.0007 89.6096 14.6281 92.9457 14.6281 97.0619C14.9667 100.129 13.0842 102.887 9.83363 102.927C6.58308 102.887 4.70045 100.129 5.03911 97.0619C5.07974 86.4889 14.2759 79.1168 24.6646 80.0854C41.2286 80.1257 48.0547 101.367 34.5792 110.904L34.5778 110.904ZM20.6551 130.476C14.3165 130.678 14.3165 139.812 20.6551 140C26.9937 139.812 26.9937 130.678 20.6551 130.476Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Some files were not shown because too many files have changed in this diff Show More