# Kneron Academy v2.0
這個應用程式是一個基於 Python、PyQt5、OpenCV 以及 Kneron SDK（kp）開發的 AI 應用 APP，使用者可以透過鏡頭、麥克風或上傳的方式經由 Kneron NPU 裝置進行實時運算。


## 目錄
- [安裝設定](#安裝設定)
- [專案架構](#專案架構)
- [功能概述](#功能概述)


## 安裝設定
- 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/
    ├── config.json
    ├── REAMDE.md
    │── 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
```
## 功能概述

- **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) 進行加密


## Script & Model 的設定
整個 utils folder 會分成兩層: global config 和 model config

model config 範例如下
``` json
{
  "display_name": "人臉偵測 (ResNet-18)",
  "description": "使用ResNet-18架構的高精度人臉偵測模型，可即時標記影像中的人臉位置",
  "model_file": "face_detection.nef",
  "input_info": {
    "type": "video",
    "supported_formats": ["mp4", "avi", "webm"]
  },
  "input_parameters": {
    "threshold": 0.75,
    "max_faces": 10,
    "tracking": true
  },
  "compatible_devices": ["KL520", "KL720"]
}
```
global config 範例如下
```json
{
  "plugins": [
    {
      "mode": "face_recognition",
      "display_name": "人臉辨識",
      "models": [
        {
          "name": "face_detection",
          "display_name": "人臉偵測 (ResNet-18)",
          "description": "基於ResNet-18的高精度人臉偵測",
          "compatible_devices": ["KL520", "KL720"]
        },
        {
          "name": "age_gender",
          "display_name": "年齡性別辨識 (VGG-Face)",
          "description": "使用VGG-Face架構辨識人臉年齡與性別",
          "compatible_devices": ["KL520", "KL720"]
        }
      ]
    },
    {
      "mode": "object_detection",
      "display_name": "物體偵測",
      "models": [
        {
          "name": "yolo_v5",
          "display_name": "物體偵測 (YOLOv5)",
          "description": "使用YOLOv5進行實時物體偵測與分類",
          "compatible_devices": ["KL720"]
        },
        {
          "name": "rcnn",
          "display_name": "精確物體識別 (Faster R-CNN)",
          "description": "以Faster R-CNN為基礎的高精度物體識別",
          "compatible_devices": ["KL720"]
        }
      ]
    }
  ]
}
```