File size: 11,949 Bytes
b81a2b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8af33ff
b81a2b3
8af33ff
 
b81a2b3
 
 
 
 
8af33ff
b81a2b3
8af33ff
b81a2b3
 
 
8af33ff
 
 
b81a2b3
8af33ff
 
 
 
 
b81a2b3
 
 
 
8af33ff
 
b81a2b3
 
8af33ff
 
 
 
b81a2b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8af33ff
 
 
b81a2b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8af33ff
b81a2b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# Tài liệu Kỹ thuật Mô hình AI — EfficientNet-B4 + CBAM
## Chẩn đoán Bệnh Võng mạc Tiểu đường (Diabetic Retinopathy Classification)

Tài liệu này mô tả chi tiết kiến trúc mô hình AI, quy trình xử lý dữ liệu đầu vào (Image Preprocessing Pipeline), cơ chế suy luận (Inference), cấu trúc Chi tiết của **File JSON Đầu ra** thu được từ mô hình và REST API, cùng hướng dẫn tích hợp cho nhà phát triển Backend / Frontend.

---

## 1. Tổng quan Hệ thống AI

Mô hình AI trong thư mục `modelAI_EfficientNetB4` được thiết kế để phân loại tự động 5 mức độ bệnh Võng mạc Tiểu đường (Diabetic Retinopathy - DR) theo tiêu chuẩn y tế quốc tế **ICDR (International Clinical Diabetic Retinopathy Disease Severity Scale)**.

### Thông số kỹ thuật chính:
* **Tên mô hình**: `EfficientNetB4_CBAM`
* **Backbone**: EfficientNet-B4 (Mạng nơ-ron tích tụ tối ưu hóa hiệu năng & độ chính xác)
* **Cơ chế Chú ý (Attention)**: CBAM (Convolutional Block Attention Module)
* **Kích thước ảnh đầu vào**: `224 × 224` pixel (3 kênh RGB)
* **Số lượng tham số**: ~17.5 triệu tham số (Backbone: ~17.5M, CBAM: ~40K)
* **Lớp đầu ra**: 5 lớp tương ứng 5 mức độ bệnh (0: No DR, 1: Mild, 2: Moderate, 3: Severe, 4: Proliferative DR)
* **Môi trường thực thi**: PyTorch 2.0+, CUDA / CPU

---

## 2. Kiến trúc Chi tiết Mô hình (Model Architecture)

Mô hình kết hợp trích xuất đặc trưng đa tầng của **EfficientNet-B4** và cơ chế lọc đặc trưng theo kênh & không gian của **CBAM Module**.

```
[Input Image: 3 x 224 x 224]


[EfficientNet-B4 Feature Extractor]

          ▼  (Tensor Shape: Batch x 1792 x 7 x 7)
[CBAM Attention Module]
 ├── 1. Channel Attention (CA) -> Tập trung vào "Kênh đặc trưng quan trọng"
 └── 2. Spatial Attention (SA) -> Tập trung vào "Vùng vị trí tổn thương"

          ▼  (Refined Feature Map: Batch x 1792 x 7 x 7)
[Adaptive Avg Pooling (1 x 1)]

          ▼  (Flatten: Batch x 1792)
[Dropout (Rate = 0.3)]


[Linear Classifier Head (1792 -> 5)]


[Raw Logits Output (5 values)]


[Softmax Function] -> Xác suất cho 5 lớp [P0, P1, P2, P3, P4]
```

### 2.1. CBAM (Convolutional Block Attention Module)
CBAM bao gồm 2 sub-modules nối tiếp:
1. **Channel Attention Sub-module**:
   - Sử dụng cả `AdaptiveAvgPool2d(1)``AdaptiveMaxPool2d(1)` để nén thông tin không gian.
   - Đi qua mạng MLP chia sẻ gồm 2 lớp `Conv2d` giảm chiều với tỷ lệ `ratio = 16` ($1792 \rightarrow 112 \rightarrow 1792$).
   - Tạo vector trọng số kênh $\mathbf{M}_c \in \mathbb{R}^{1792 \times 1 \times 1}$ qua hàm Sigmoid và nhân bản phần tử với feature map.
2. **Spatial Attention Sub-module**:
   - Gom thông tin kênh bằng phép tính `mean(dim=1)` và `max(dim=1)` tạo tensor 2 kênh.
   - Cho qua lớp `Conv2d(2 -> 1, kernel_size=7, padding=3)` và Sigmoid để tạo ma trận trọng số không gian $\mathbf{M}_s \in \mathbb{R}^{1 \times H \times W}$.
   - Nhân phần tử với feature map để giúp mô hình tập trung vào các vùng tổn thương võng mạc (vi phình mạch, xuất huyết, xuất tiết cứng/mềm).

---

## 3. Quy trình Xử lý Ảnh Đầu vào (Preprocessing Pipeline)

Trước khi đưa ảnh đáy mắt (Fundus Photo) vào mô hình AI, dữ liệu được truyền qua pipeline xử lý ảnh 5 bước trong `preprocessing.py`:

```
[Ảnh gốc (File / Bytes / PIL / Array)]

                 ▼  1. load_image()
[Mảng BGR OpenCV (Numpy Array)]

                 ▼  2. auto_detect_border() & crop_fundus_circle()
[Ảnh đã cắt bỏ viền đen]

                 ▼  3. letterbox_resize(target_size=(224, 224))
[Ảnh 224x224 bảo toàn tỷ lệ aspect ratio (Đệm đen)]

                 ▼  4. ben_graham_transform()
[Ảnh tăng cường tương phản Ben Graham]

                 ▼  5. prepare_image_tensor()
[PyTorch Tensor (1, 3, 224, 224) - Normalized ImageNet]
```

### Các bước xử lý chi tiết:

1. **Chuẩn hóa định dạng đầu vào (`load_image`)**:
   - Hỗ trợ đường dẫn file (`str`), mảng byte (`bytes`), đối tượng PIL Image, hoặc mảng NumPy.
   - Chuyển đổi tất cả về định dạng chuẩn OpenCV BGR (`uint8`).

2. **Cắt bỏ viền đen tự động (`crop_fundus_circle`)**:
   - Xác định ngưỡng tối `CROP_TOLERANCE = 12`.
   - Tìm Bounding Box của vùng cầu mắt có chứa thông tin y tế (`cv2.findNonZero`) và crop loại bỏ viền đen vô ích xung quanh.

3. **Letterbox Resize (`letterbox_resize`)**:
   - Thay vì co giãn làm biến dạng hình dạng tổn thương mắt, ảnh được scale giữ nguyên tỷ lệ chiều rộng/chiều cao.
   - Đệm thêm viền đen cân đối để đạt kích thước cố định `(224, 224)`.

4. **Biến đổi Ben Graham (`ben_graham_transform`)**:
   - Áp dụng công thức lọc nhiễu & nổi bật mạch máu/tổn thương:
     $$\text{Output} = \text{clip}(4 \times I - 4 \times \text{GaussianBlur}(I, \sigma=10) + 128, 0, 255)$$
   - Cân bằng ánh sáng giữa các ảnh chụp từ nhiều thiết bị soi đáy mắt khác nhau.

5. **Chuyển đổi Tensor & Normalization**:
   - Chuyển mảng BGR sang RGB.
   - Đưa về dải giá trị $[0.0, 1.0]$.
   - Chuẩn hóa theo chỉ số ImageNet: Mean `[0.485, 0.456, 0.406]`, Std `[0.229, 0.224, 0.225]`.
   - Mở rộng chiều batch: Tensor shape `(1, 3, 224, 224)`.

---

## 4. Cách Mô hình Xử lý & Tạo ra File JSON Kết quả

Khi nhận yêu cầu phân loại, mô hình AI thực thi theo trình tự sau:

1. **Nhận dữ liệu & Tiền xử lý**: Mảng ảnh được chuẩn hóa thành PyTorch Tensor.
2. **Forward Pass**: Tensor được đẩy qua mô hình `EfficientNetB4_CBAM`.
3. **Softmax Scoring**: Tính xác suất cho từng nhãn:
   $$P(y = i | X) = \frac{e^{z_i}}{\sum_{j=0}^{4} e^{z_j}}$$
4. **Xác định Nhãn Dự đoán & Độ tin cậy**:
   - `class_id` = $\arg\max_i P(y=i|X)$
   - `confidence` = $\max_i P(y=i|X)$
5. **Đóng gói Kết quả JSON**:
   - Trích xuất bảng xác suất cho tất cả 5 nhãn.
   - Trả về đối tượng JSON chứa 4 trường: `class_id`, `class_name`, `confidence`, `probabilities`.

---

## 5. Cấu trúc File JSON Đầu ra (JSON Output Specification)

Định dạng JSON phản hồi từ `DRPredictor.predict()` (Python Core / SDK) cũng như REST API (`POST /api/predict`):

#### Ví dụ JSON Response chuẩn (HTTP 200 OK):

```json
{
  "class_id": 0,
  "class_name": "No DR",
  "confidence": 0.9945334196090698,
  "probabilities": {
    "No DR": 0.9945334196090698,
    "Mild": 0.0008030196186155081,
    "Moderate": 0.0019999665673822165,
    "Severe": 0.0011487160809338093,
    "Proliferative DR": 0.0015149053651839495
  }
}
```

#### Mô tả chi tiết các trường dữ liệu:

| Trường (Field) | Kiểu dữ liệu | Mô tả |
|---|---|---|
| `class_id` | `integer` | Chỉ số mức độ bệnh từ `0` đến `4`. |
| `class_name` | `string` | Tên tiếng Anh chuẩn của nhãn ICDR tương ứng (`No DR`, `Mild`, `Moderate`, `Severe`, `Proliferative DR`). |
| `confidence` | `float` | Giá trị độ tin cậy của mô hình cho nhãn dự đoán (xác suất thô từ `0.0` đến `1.0`). |
| `probabilities` | `object` | Bảng xác suất chi tiết của cả 5 nhãn ICDR. |

---

## 6. Danh mục Lời khuyên Y tế Lâm sàng (Clinical Guidance Table)

Bảng ánh xạ từ `class_id` ra chỉ dẫn y tế và màu sắc giao diện:

| Class ID | Nhãn ICDR | Tiêu đề Tiếng Việt (`title`) | Mức khẩn cấp (`urgency`) | Mã màu (`badge_color`) |
|:---:|---|---|---|:---:|
| **0** | `No DR` | Mắt Bình Thường (No DR) | Bình thường | `#10b981` (Xanh lá) |
| **1** | `Mild` | Bệnh Nhẹ (Mild DR) | Theo dõi định kỳ | `#3b82f6` (Xanh dương) |
| **2** | `Moderate` | Bệnh Trung Bình (Moderate DR) | Khám chuyên khoa | `#f59e0b` (Cam vàng) |
| **3** | `Severe` | Bệnh Nặng (Severe DR) | Cần can thiệp sớm | `#ff0000` (Đỏ tươi) |
| **4** | `Proliferative DR` | Tăng Sinh Nguy Hiểm (Proliferative DR) | KHẨN CẤP | `#5e0101` (Đỏ thẫm) |

---

## 7. Hướng dẫn Tích hợp API (API Integration Guide)

### 7.1. Khởi chạy REST API Server
```bash
# Di chuyển vào thư mục modelAI_EfficientNetB4
cd modelAI_EfficientNetB4

# Chạy server uvicorn
python main_api.py
```
Server sẽ chạy tại địa chỉ: `http://localhost:8000`. Bạn có thể truy cập `/docs` để mở giao diện Swagger UI tương tác.

---

### 7.2. Các Endpoints

#### 1. Kiểm tra trạng thái máy chủ
* **URL**: `GET /`
* **Response**:
```json
{
  "message": "AI Diabetic Retinopathy API Service is running.",
  "docs_url": "/docs",
  "health_check": "/api/info",
  "predict_endpoint": "POST /api/predict"
}
```

#### 2. Thông tin mô hình AI
* **URL**: `GET /api/info`
* **Response**:
```json
{
  "status": "online",
  "model_name": "EfficientNetB4_CBAM",
  "num_classes": 5,
  "device": "cuda:0",
  "classes": {
    "0": "No DR",
    "1": "Mild",
    "2": "Moderate",
    "3": "Severe",
    "4": "Proliferative DR"
  }
}
```

#### 3. Chẩn đoán ảnh đáy mắt
* **URL**: `POST /api/predict`
* **Content-Type**: `multipart/form-data`
* **Body Form-Data**: `file`: [File ảnh PNG / JPG / JPEG]

---

### 7.3. Ví dụ Code Gọi API

#### A. cURL Command:
```bash
curl -X POST "http://localhost:8000/api/predict" \
  -H "accept: application/json" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/fundus_image.jpg"
```

#### B. Python Code (requests):
```python
import requests

url = "http://localhost:8000/api/predict"
file_path = "test_eye.jpg"

with open(file_path, "rb") as f:
    files = {"file": (file_path, f, "image/jpeg")}
    response = requests.post(url, files=files)

data = response.json()
print("Kết quả chẩn đoán:", data["class_name"])
print("Độ tin cậy:", data["confidence"])
print("Xác suất từng lớp:", data["probabilities"])
```

#### C. JavaScript (Fetch API - Frontend React/Vue/Vanilla):
```javascript
async function predictFundusImage(fileInput) {
  const formData = new FormData();
  formData.append("file", fileInput.files[0]);

  const response = await fetch("http://localhost:8000/api/predict", {
    method: "POST",
    body: formData
  });

  const result = await response.json();
  console.log("JSON Trả về từ AI:", result);
  // { class_id, class_name, confidence, probabilities }
}
```

---

## 8. Xử lý Lỗi (Error Handling & HTTP Status Codes)

| Status Code | Nguyên nhân phát sinh | Cấu trúc JSON Lỗi |
|:---:|---|---|
| `400 Bad Request` | File tải lên không phải định dạng ảnh hợp lệ (VD: PDF, TXT). | `{"detail": "File tải lên không phải là định dạng ảnh hợp lệ."}` |
| `500 Internal Error` | Không nạp được file weights `.pth` hoặc lỗi bộ nhớ GPU/CPU trong quá trình xử lý ảnh. | `{"detail": "Lỗi trong quá trình xử lý ảnh: [chi tiết lỗi]"}` |

---

## 9. Đóng gói Docker Container

Để triển khai hệ thống lên môi trường Server / Cloud:

```bash
# Build image Docker
docker build -t dr-efficientnet-api .

# Chạy container
docker run -d -p 8000:8000 --name dr_ai_service dr-efficientnet-api
```
Hoặc khởi chạy thông qua `docker-compose`:
```bash
docker-compose up -d
```