mobilenet-webnn / demo.py
tarekziade's picture
tarekziade HF Staff
Upload demo
442e014 verified
Raw
History Blame
4.48 kB
#!/usr/bin/env python3
"""
MobileNetV2 Image Classification using PyWebNN
- model_id: "tarekziade/mobilenet-webnn"
- backend: "cpu"
- force_download: False
Usage:
$ pip install pywebnn pillow
$ python demo.py /path/to/image.jpg
"""
import sys
import time
from pathlib import Path
import numpy as np
from PIL import Image
import webnn
MODEL_ID = "tarekziade/mobilenet-webnn"
BACKEND = "cpu" # "cpu" | "gpu" | "coreml"
FORCE_DOWNLOAD = False
def load_imagenet_labels():
labels_file = Path(__file__).with_name("imagenet_classes.txt")
if not labels_file.exists():
import urllib.request
url = (
"https://raw.githubusercontent.com/pytorch/hub/master/imagenet_classes.txt"
)
print(" [DOWNLOAD] ImageNet labels...")
urllib.request.urlretrieve(url, labels_file)
print(" [OK] Labels downloaded")
return [line.strip() for line in labels_file.read_text().splitlines()]
IMAGENET_CLASSES = load_imagenet_labels()
def preprocess_image(image_path: Path) -> np.ndarray:
img = Image.open(image_path).convert("RGB")
img = img.resize((224, 224), Image.Resampling.BILINEAR)
x = np.asarray(img, dtype=np.float32) / 255.0
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
x = (x - mean) / std
x = np.transpose(x, (2, 0, 1)) # HWC -> CHW
x = np.expand_dims(x, 0) # add batch
return x
def backend_settings(backend: str):
if backend == "cpu":
return False, "default", "ONNX CPU"
if backend == "gpu":
return True, "high-performance", "ONNX GPU"
if backend == "coreml":
return True, "high-performance", "CoreML (Neural Engine)"
raise ValueError(f"Unknown BACKEND: {backend!r}")
def main():
if len(sys.argv) != 2:
print(f"Usage: {Path(sys.argv[0]).name} /path/to/image.jpg")
sys.exit(2)
image_path = Path(sys.argv[1])
if not image_path.exists():
print(f"Error: Image not found: {image_path}")
sys.exit(1)
accelerated, power, backend_name = backend_settings(BACKEND)
print("=" * 70)
print("MobileNetV2 Image Classification (Hugging Face Hub)")
print("=" * 70)
print(f"Image: {image_path}")
print(f"Model: {MODEL_ID}")
print(f"Backend: {backend_name}")
print()
hub = webnn.Hub()
print("Downloading model from Hugging Face Hub...")
t0 = time.time()
model_files = hub.download_model(MODEL_ID, force=FORCE_DOWNLOAD)
download_ms = (time.time() - t0) * 1000
print(f" [OK] Downloaded ({download_ms:.2f}ms)")
print(f" - Graph: {Path(model_files['graph']).name}")
print()
print("Loading graph...")
t0 = time.time()
graph = webnn.MLGraph.load(
model_files["graph"],
manifest_path=model_files["manifest"],
weights_path=model_files["weights"],
)
load_ms = (time.time() - t0) * 1000
print(f" [OK] Loaded ({load_ms:.2f}ms)")
print()
print("Preprocessing image...")
t0 = time.time()
input_data = preprocess_image(image_path)
prep_ms = (time.time() - t0) * 1000
print(f" [OK] {input_data.shape} ({prep_ms:.2f}ms)")
print()
print("Creating WebNN context...")
ml = webnn.ML()
context = ml.create_context(power_preference=power, accelerated=accelerated)
print(f" [OK] Context created (accelerated={context.accelerated})")
print()
print("Running inference...")
t0 = time.time()
results = context.compute(graph, {"input": input_data})
inf_ms = (time.time() - t0) * 1000
print(f" [OK] Done ({inf_ms:.2f}ms)")
print()
probs = results["output"][0]
top5 = np.argsort(probs)[-5:][::-1]
print("Top 5 Predictions:")
print("-" * 70)
for rank, idx in enumerate(top5, 1):
name = IMAGENET_CLASSES[int(idx)]
conf = float(probs[int(idx)]) * 100.0
print(f" {rank}. {name:50s} {conf:6.2f}%")
print()
total_ms = download_ms + load_ms + prep_ms + inf_ms
print("=" * 70)
print("Performance Summary:")
print(f" - Model Download: {download_ms:.2f}ms")
print(f" - Graph Load: {load_ms:.2f}ms")
print(f" - Preprocessing: {prep_ms:.2f}ms")
print(f" - Inference: {inf_ms:.2f}ms")
print(f" - Total Time: {total_ms:.2f}ms")
print("=" * 70)
print()
print(f"[OK] Done. Cache dir: {hub.cache_dir}")
if __name__ == "__main__":
main()