88 lines
5.2 KiB
Markdown
88 lines
5.2 KiB
Markdown
Nhìn vào bản Walkthrough bạn vừa cung cấp, bạn đã phát hiện ra một chi tiết cực kỳ chính xác: **Nhóm phát triển chưa hề thêm file mô hình `.tflite` (như MiDaS) vào dự án, mà họ đang "ăn gian" toán học bằng cách giả lập Bản đồ chiều sâu (Simulated Depth Map) từ chính mặt nạ 2D của ML Kit.**
|
|
|
|
Hãy nhìn kỹ vào dòng này trong Walkthrough của họ:
|
|
|
|
> *Calculates a simulated monocular depth map from the ML Kit segmentation confidence mask:* `distance = 1.0f - confidence`.
|
|
|
|
---
|
|
|
|
## 🔍 Phân tích cách họ đang làm (Giả lập thay vì dùng AI Depth thật)
|
|
|
|
Thay vì tốn thêm bộ nhớ tải file mô hình nặng và gây lag máy, họ tận dụng luôn mảng số thực `confidence` (độ tin cậy từ `0.0` đến `1.0`) của mô hình **ML Kit Segmentation** sẵn có:
|
|
|
|
* Ở vùng ruột đối tượng (giữa khuôn mặt, thân mình): `confidence` gần bằng `1.0` $\rightarrow$ `distance` gần bằng `0.0` (Vùng tiêu cự $\rightarrow$ Giữ nét).
|
|
* Ở vùng biên tiếp giáp (rìa tai, tóc mảnh, vai): `confidence` giảm dần từ `0.8` xuống `0.2` $\rightarrow$ `distance` tăng dần từ `0.2` lên `0.8` (Vùng chuyển tiếp $\rightarrow$ Nhặt pixel mờ tăng dần từ lớp 1 sang lớp 2).
|
|
* Ở vùng nền hoàn toàn: `confidence` bằng `0.0` $\rightarrow$ `distance` bằng `1.0` (Hậu cảnh vô cực $\rightarrow$ Mờ đại lớp 3).
|
|
|
|
Cách làm này rất khôn ngoan vì nó **vừa giải quyết được lỗi cắt lẹm viền tai/tóc** nhờ dải mờ gradient ở biên, **vừa không làm tăng dung lượng app** và giữ tốc độ xử lý nhanh. Tuy nhiên, điểm yếu của nó là **nền nhà hay hàng cây ở xa tít cũng sẽ bị mờ giống hệt bức tường ngay sau lưng bạn** (vì chúng đều có chung `confidence = 0`).
|
|
|
|
---
|
|
|
|
## 🛠️ Kế hoạch Markdown bổ sung: Cấu hình File mô hình MiDaS thực tế (Nếu bạn muốn nâng cấp lên Depth thật)
|
|
|
|
Nếu bạn muốn nâng cấp lên bản đồ chiều sâu vật lý thực sự (vật càng xa càng mờ đúng nghĩa) chứ không chấp nhận cách giả lập dựa trên viền của ML Kit, bạn cần bổ sung các bước tạo và cấu hình file mô hình theo kế hoạch dưới đây:
|
|
|
|
### 📦 1. Khai báo thư mục tài nguyên (`build.gradle`)
|
|
|
|
Mô hình AI `.tflite` sẽ không được giải nén và nén lại để tối ưu hóa hiệu năng, bạn cần cấu hình cho Android Gradle không nén file này trong `app/build.gradle`:
|
|
|
|
```groovy
|
|
android {
|
|
...
|
|
aaptOptions {
|
|
noCompress "tflite" // Giữ nguyên file mô hình để tăng tốc độ nạp vào bộ nhớ RAM
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
### 📥 2. Quy trình tải và đặt file Mô hình AI
|
|
|
|
1. Tải file mô hình ước tính chiều sâu tối ưu cho di động: `midas_v21_small_256.tflite` (Dung lượng khoảng ~15MB).
|
|
2. Tạo thư mục tài nguyên trong cấu trúc dự án Android Native: `app/src/main/assets/models/`.
|
|
3. Di chuyển file vừa tải vào đúng đường dẫn: `app/src/main/assets/models/midas.tflite`.
|
|
|
|
### 💻 3. Nạp và xử lý ma trận Depth Map thực tế trong `MainActivity.kt`
|
|
|
|
Thay vì tính toán bằng công thức `1.0f - confidence`, mã nguồn Java/Kotlin sẽ gọi lớp `Interpreter` của TensorFlow Lite để quét song song với ML Kit:
|
|
|
|
```kotlin
|
|
import org.tensorflow.lite.Interpreter
|
|
import java.io.FileInputStream
|
|
import java.nio.channels.FileChannel
|
|
|
|
class DepthEstimationEngine(context: Context) {
|
|
private var tflite: Interpreter? = null
|
|
|
|
init {
|
|
// Nạp file mô hình từ thư mục assets vào hệ thống
|
|
val assetFileDescriptor = context.assets.openFd("models/midas.tflite")
|
|
val inputStream = FileInputStream(assetFileDescriptor.fileDescriptor)
|
|
val fileChannel = inputStream.channel
|
|
val startOffset = assetFileDescriptor.startOffset
|
|
val declaredLength = assetFileDescriptor.declaredLength
|
|
val modelBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
|
|
|
|
tflite = Interpreter(modelBuffer)
|
|
}
|
|
|
|
fun runInference(inputBitmap: Bitmap): Array<Array<FloatArray>> {
|
|
// Chuyển đổi Bitmap ảnh chụp về ma trận kích thước 256x256 đầu vào của MiDaS
|
|
val inputBuffer = convertBitmapToByteBuffer(inputBitmap)
|
|
|
|
// Mảng đầu ra chứa ma trận chiều sâu thực tế của bức ảnh (Distance thực tế)
|
|
val outputDepthMap = Array(1) { Array(256) { FloatArray(256) } }
|
|
|
|
tflite?.run(inputBuffer, outputDepthMap)
|
|
return outputDepthMap
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 📅 4. Checklist Xác Minh Bản Sửa Đổi (Verification)
|
|
|
|
* [ ] **Lựa chọn giải pháp:** Bạn quyết định giữ nguyên cách làm hiện tại của Walkthrough (Dùng thuật toán giả lập từ ML Kit để tiết kiệm tài nguyên nhưng viền mượt) hay muốn ép cấu hình nạp mô hình MiDaS thực tế (Mờ sâu vật lý nhưng tốn thêm 15MB dung lượng app)?
|
|
* [ ] Run lệnh build để kiểm tra độ tương thích nếu thêm thư viện TFLite: `./gradlew assembleDebug`. |