levietanh's picture
Upload source code and template matching images
a39fe42
Raw
History Blame Contribute Delete
2.57 kB
from __future__ import annotations
from typing import Dict, Tuple
import numpy as np
import timm
import torch
import torch.nn.functional as F
from PIL import Image
from timm.data import create_transform, resolve_data_config
class ModelManager:
"""Quản lý mô hình timm và trích xuất embedding ảnh."""
def __init__(self, device: str | None = None) -> None:
"""Khởi tạo manager và chọn thiết bị chạy (CPU/GPU)."""
if device is None:
device = "cuda" if torch.cuda.is_available() else "cpu"
self.device = device
self._models: Dict[str, torch.nn.Module] = {}
self._transforms: Dict[str, object] = {}
def _build(self, model_name: str) -> Tuple[torch.nn.Module, object]:
"""Tạo model và transform tương ứng theo tên model."""
model = timm.create_model(
model_name,
pretrained=True,
num_classes=0,
global_pool="avg",
)
model.eval().to(self.device)
config = resolve_data_config({}, model=model)
transform = create_transform(**config)
return model, transform
def get(self, model_name: str) -> Tuple[torch.nn.Module, object]:
"""Lấy model và transform đã cache hoặc tạo mới."""
if model_name not in self._models:
model, transform = self._build(model_name)
self._models[model_name] = model
self._transforms[model_name] = transform
return self._models[model_name], self._transforms[model_name]
def embed(self, model_name: str, image_rgb: np.ndarray) -> torch.Tensor:
"""Trích xuất embedding từ ảnh RGB bằng model chỉ định."""
model, transform = self.get(model_name)
return self.embed_with(model, transform, image_rgb)
def embed_with(self, model: torch.nn.Module, transform, image_rgb: np.ndarray) -> torch.Tensor:
"""Trích xuất embedding từ ảnh RGB với model/transform đã cache."""
pil_img = Image.fromarray(image_rgb)
tensor = transform(pil_img).unsqueeze(0).to(self.device)
with torch.no_grad():
feat = model(tensor)
return feat.squeeze(0)
def cosine_similarity(self, a: torch.Tensor, b: torch.Tensor) -> float:
"""Tính cosine similarity giữa hai embedding."""
a_norm = F.normalize(a, dim=0)
b_norm = F.normalize(b, dim=0)
return float(F.cosine_similarity(a_norm, b_norm, dim=0).item())