Keypoint Detection
LiteRT
Core ML
ONNX
ExecuTorch
LiteRT
anira
mediapipe
hand-tracking
gesture-recognition
real-time
libtorch
vulkan
Instructions to use anira-project/mediapipe-gesture-recognizer with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use anira-project/mediapipe-gesture-recognizer with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
File size: 4,548 Bytes
d14a776 8126118 d14a776 7d4dc70 d14a776 14874fc d14a776 8126118 14874fc d14a776 8126118 d14a776 7d4dc70 d14a776 8126118 d14a776 14874fc d14a776 7d4dc70 d14a776 14874fc d14a776 14874fc d14a776 14874fc d14a776 8126118 d14a776 14874fc 8126118 d14a776 8126118 14874fc d14a776 14874fc d14a776 | 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 | # SPDX-License-Identifier: Apache-2.0
# /// script
# requires-python = ">=3.11,<3.13"
# dependencies = ["executorch==1.3.1", "torch==2.12.0", "coremltools", "onnx2torch", "onnxsim", "onnx", "onnxruntime", "numpy"]
# ///
"""Exports the four hand tracking models to ExecuTorch (.pte, XNNPACK: every CPU platform).
The models exist as TFLite (MediaPipe) and our ONNX conversions only; ExecuTorch takes a PyTorch
module, which onnx_to_torch.py makes from each ONNX model. It is exported with torch.export, lowered,
and checked against ONNX Runtime on the same random input. ExecuTorch 1.3.1 is the runtime
anira's backends ship; its Python bindings are built against torch 2.12.0, hence the pin.
uv run export_executorch.py <weights dir laid out like the HF repo> [--coreml | --vulkan]
writes <weights dir>/executorch/<model>.pte, lowered to XNNPACK (every CPU platform), or with
--coreml <model>_coreml.pte, lowered to Core ML (Apple platforms) in float16 for the Neural Engine,
checked against ONNX Runtime relative to each output's peak, or with --vulkan <model>_vulkan.pte,
lowered to Vulkan (GPUs with Vulkan), exported but not run: Python's ExecuTorch runtime has no
Vulkan delegate.
"""
import os
import sys
import numpy as np
import onnxruntime
import torch
import coremltools as ct
from executorch.backends.apple.coreml.compiler import CoreMLBackend
from executorch.backends.apple.coreml.partition import CoreMLPartitioner
from executorch.backends.xnnpack.partition.xnnpack_partitioner import XnnpackPartitioner
from executorch.exir import to_edge_transform_and_lower
from executorch.runtime import Runtime
from onnx_to_torch import MODELS, torch_module
TOLERANCE = 1e-3
TOLERANCE_COREML = 1e-2 # float16, relative to the output's peak
def export(weights, name, coreml, vulkan=False):
onnx_path = os.path.join(weights, "onnx", f"{name}.onnx")
module, shapes = torch_module(onnx_path)
generator = torch.Generator().manual_seed(0)
inputs = tuple(torch.rand(*dims, generator=generator) for dims in shapes.values())
edge = to_edge_transform_and_lower(torch.export.export(module, inputs),
partitioner=[partitioner(coreml, vulkan)])
program = edge.to_executorch()
os.makedirs(os.path.join(weights, "executorch"), exist_ok=True)
suffix = "_coreml" if coreml else "_vulkan" if vulkan else ""
pte_path = os.path.join(weights, "executorch", f"{name}{suffix}.pte")
with open(pte_path, "wb") as f:
f.write(program.buffer)
if vulkan:
print(f"{name}: {vulkan_summary(edge)}")
return
session = onnxruntime.InferenceSession(onnx_path)
expected = session.run(None, {v.name: x.numpy() for v, x in zip(session.get_inputs(), inputs)})
method = Runtime.get().load_program(pte_path).load_method("forward")
actual = method.execute(list(inputs))
if coreml:
worst = max(float(np.max(np.abs(e - a.numpy()))) / (1.0 + float(np.max(np.abs(e))))
for e, a in zip(expected, actual))
else:
worst = max(float(np.max(np.abs(e - a.numpy()))) for e, a in zip(expected, actual))
engine = "ExecuTorch Core ML" if coreml else "ExecuTorch"
print(f"{name}: {len(program.buffer)} bytes, max |{engine} - ONNX Runtime| = {worst:.2e}")
if worst > (TOLERANCE_COREML if coreml else TOLERANCE):
sys.exit(f"{name}: the export differs from ONNX Runtime by {worst:.2e}")
def partitioner(coreml, vulkan=False):
if vulkan:
from executorch.backends.vulkan.partitioner.vulkan_partitioner import VulkanPartitioner
return VulkanPartitioner()
if not coreml:
return XnnpackPartitioner()
return CoreMLPartitioner(compile_specs=CoreMLBackend.generate_compile_specs(
compute_precision=ct.precision.FLOAT16, compute_unit=ct.ComputeUnit.ALL))
def main():
coreml = "--coreml" in sys.argv[2:]
vulkan = "--vulkan" in sys.argv[2:]
for name in MODELS:
export(sys.argv[1], name, coreml, vulkan)
def vulkan_summary(edge):
"""Python's ExecuTorch runtime has no Vulkan delegate: a Vulkan program is counted, not run."""
graph = edge.exported_program().graph
calls = [n for n in graph.nodes if n.op == "call_function" and "getitem" not in str(n.target)]
delegated = sum(1 for n in calls if "executorch_call_delegate" in str(n.target))
return (f"Vulkan: {delegated} delegated subgraphs, {len(calls) - delegated} operators left to the portable "
"CPU kernels; not run here")
if __name__ == "__main__":
main()
|