TensorFlow Lite Task API는 매우 편리한 고수준 Vision API지만, 사전 요구사항이 까다롭다. 특히 **Teachable Machine**이나 **TensorFlow Hub**에서 다운로드한 `.pb` 모델은 바로 Android에서 쓸 수 없다.
이 포스팅에서는 `.pb` 모델을 Android에서 Task API로 사용하기까지의 **전체 전환 흐름**을 정리한다.
---
## 🧠 왜 안 되는가?
### ❌ Android TFLite Task API에서 바로 사용할 수 없는 이유
- 대부분의 `.pb` 모델은 **TFLite 포맷이 아님**
- 또는 `.tflite`라고 해도 **Metadata (NormalizationOptions 등)** 가 없어 Task API가 실패
- 에러 메시지 예시:
Input tensor has type kTfLiteFloat32: it requires specifying NormalizationOptions metadata…
---
## ✅ 해결 순서 요약
1. **(필요시) `tfhub_module.pb` → SavedModel 변환**
2. `SavedModel` → `.tflite` 변환
3. `.tflite` → Metadata 추가
4. Android Task API에서 정상 로드
---
## 🛠 Step-by-Step
### 1. `tfhub_module.pb` → `SavedModel` 변환
```python
import tensorflow as tf
graph_def = tf.compat.v1.GraphDef()
with tf.io.gfile.GFile("tfhub_module.pb", "rb") as f:
graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
tf.import_graph_def(graph_def, name="")
for op in graph.get_operations():
print(op.name) # input/output 이름 확인
@tf.function(input_signature=[tf.TensorSpec([1, 224, 224, 3], tf.float32)])
def model_fn(x):
return {"output": tf.import_graph_def(graph_def, input_map={"input": x}, return_elements=["output:0"])[0]}
concrete_func = model_fn.get_concrete_function()
tf.saved_model.save(concrete_func, "./saved_model")
2. SavedModel → TFLite 변환
converter = tf.lite.TFLiteConverter.from_saved_model("./saved_model")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float32]
tflite_model = converter.convert()
with open("model.tflite", "wb") as f:
f.write(tflite_model)
3. Metadata 추가 (NormalizationOptions 등)
from tflite_support.metadata_writers import image_classifier
from tflite_support.metadata_writers import writer_utils
MODEL_PATH = "model.tflite"
LABEL_FILE = "labels.txt" # 각 줄마다 클래스명
SAVE_TO_PATH = "model_with_metadata.tflite"
writer = image_classifier.MetadataWriter.create_for_inference(
MODEL_PATH, [LABEL_FILE], norm_mean=[127.5], norm_std=[127.5]
)
writer_utils.save_file(writer.populate(), SAVE_TO_PATH)
- 이 과정을 거쳐야 GMS 기반 Task API에서 정상 로드됨
4. Android에서 로드
val options = ObjectDetector.ObjectDetectorOptions.builder()
.setMaxResults(3)
.build()
val objectDetector = ObjectDetector.createFromFileAndOptions(
context,
"model_with_metadata.tflite",
options
)
🧪 에러가 날 때 체크 포인트
체크리스트 | 설명 |
---|---|
Tensor 이름 | input:0 , output:0 등 정확한 이름 필요 |
Tensor 타입 | float32일 경우 normalization metadata 필요 |
Label 파일 | .tflite 에 포함되어야 Task API가 클래스명 매핑 가능 |
입력 스펙 | 이미지 shape은 [1, 224, 224, 3] 등이 일반적 |
✅ 마무리
Task API는 편리하지만, 모델 준비가 까다롭다.
이 과정을 자동화하려면 CLI 도구 대신 Python 스크립트를 활용하자.
특히 TFHub/Teachable Machine 모델은 반드시 metadata 추가 후 사용해야 Android에서 제대로 동작한다.
최종 산출물: model_with_metadata.tflite
이 모델만 있으면 Android 앱에서 바로 GMS Task API 기반 객체 탐지가 가능하다!