initialize method

Future<void> initialize({
  1. HandMode mode = HandMode.boxesAndLandmarks,
  2. HandLandmarkModel landmarkModel = HandLandmarkModel.full,
  3. double detectorConf = 0.45,
  4. double palmNmsIou = 0.45,
  5. double palmRoiScale = 2.6,
  6. int maxDetections = 10,
  7. double minLandmarkScore = 0.5,
  8. bool enableTracking = false,
  9. TrackingConfig trackingConfig = const TrackingConfig(),
  10. int interpreterPoolSize = 1,
  11. PerformanceConfig performanceConfig = const PerformanceConfig(),
  12. bool enableGestures = false,
  13. double gestureMinConfidence = 0.5,
  14. bool useCompiledModel = false,
  15. String liteRtAccelerator = 'auto',
  16. Set<Accelerator> accelerators = const {Accelerator.gpu, Accelerator.cpu},
  17. Precision precision = Precision.fp16,
})

Initializes the hand detector by loading TensorFlow Lite models.

Must be called before detect or detectFromMat. Calling initialize twice without dispose throws StateError.

Parameters:

  • mode: Detection mode (boxes only or boxes + landmarks). Default: HandMode.boxesAndLandmarks
  • landmarkModel: Hand landmark model variant. Default: HandLandmarkModel.full
  • detectorConf: Palm detection confidence threshold (0.0-1.0). Default: 0.45
  • palmNmsIou: IoU threshold for palm non-maximum suppression (0.0-1.0). Higher keeps more overlapping detections; lower merges them harder. Default: 0.45
  • palmRoiScale: Expansion factor for the palm ROI fed to the landmark model. Larger includes more context around the palm. Default: 2.6
  • maxDetections: Maximum number of hands to detect. Default: 10
  • minLandmarkScore: Minimum landmark confidence score (0.0-1.0). Default: 0.5
  • interpreterPoolSize: Number of landmark model interpreter instances (1-10). Default: 1. Forced to 1 when a performance delegate (XNNPACK/auto) is enabled.
  • performanceConfig: TensorFlow Lite performance configuration. Default: auto (optimal per platform)
  • enableGestures: Whether to run gesture recognition. Default: false
  • gestureMinConfidence: Minimum confidence for gesture recognition (0.0-1.0). Default: 0.5
  • useCompiledModel: Use the LiteRT Next CompiledModel engine (GPU with CPU fallback) instead of the classic Interpreter engine. Default: false. When enabled, the landmark model runs on a pool of interpreterPoolSize CompiledModel instances (default 1) — one model per concurrently-detected hand, each with its own input buffer.
  • enableTracking: Enable MediaPipe-style detection + tracking. When true, each detected hand is followed frame-to-frame via a landmark-derived region of interest, and the palm detector only runs to find new hands. This greatly reduces overlay drop-outs on video. Call resetTracking between unrelated inputs. Default: false (palm detection every frame).
  • trackingConfig: Tuning for the ROI carried between frames when enableTracking is true (expansion, shift, association IoU, size bounds). Ignored when tracking is off. Default: TrackingConfig (MediaPipe values).

Implementation

Future<void> initialize({
  HandMode mode = HandMode.boxesAndLandmarks,
  HandLandmarkModel landmarkModel = HandLandmarkModel.full,
  double detectorConf = 0.45,
  double palmNmsIou = 0.45,
  double palmRoiScale = 2.6,
  int maxDetections = 10,
  double minLandmarkScore = 0.5,
  bool enableTracking = false,
  TrackingConfig trackingConfig = const TrackingConfig(),
  int interpreterPoolSize = 1,
  PerformanceConfig performanceConfig = const PerformanceConfig(),
  bool enableGestures = false,
  double gestureMinConfidence = 0.5,
  bool useCompiledModel = false,
  // Web-only (LiteRT.js accelerator); accepted for cross-platform API parity
  // and ignored on native, which selects its engine via useCompiledModel.
  String liteRtAccelerator = 'auto',
  Set<Accelerator> accelerators = const {Accelerator.gpu, Accelerator.cpu},
  Precision precision = Precision.fp16,
}) async {
  if (isReady) {
    throw StateError('HandDetector already initialized');
  }

  const palmPath =
      'packages/hand_detection/assets/models/hand_detection.tflite';
  const landmarkPath =
      'packages/hand_detection/assets/models/hand_landmark_full.tflite';

  final assetFutures = <Future<ByteData>>[
    rootBundle.load(palmPath),
    rootBundle.load(landmarkPath),
  ];

  if (enableGestures) {
    const embedderPath =
        'packages/hand_detection/assets/models/gesture_embedder.tflite';
    const classifierPath =
        'packages/hand_detection/assets/models/canned_gesture_classifier.tflite';
    assetFutures.add(rootBundle.load(embedderPath));
    assetFutures.add(rootBundle.load(classifierPath));
  }

  final results = await Future.wait(assetFutures);

  final palmBytes = results[0].buffer.asUint8List();
  final landmarkBytes = results[1].buffer.asUint8List();

  Uint8List? gestureEmbedderBytes;
  Uint8List? gestureClassifierBytes;
  if (enableGestures && results.length > 2) {
    gestureEmbedderBytes = results[2].buffer.asUint8List();
    gestureClassifierBytes = results[3].buffer.asUint8List();
  }

  final effectivePoolSize = performanceConfig.mode == PerformanceMode.disabled
      ? interpreterPoolSize
      : 1;

  await initializeFromBuffers(
    palmDetectionBytes: palmBytes,
    handLandmarkBytes: landmarkBytes,
    gestureEmbedderBytes: gestureEmbedderBytes,
    gestureClassifierBytes: gestureClassifierBytes,
    mode: mode,
    landmarkModel: landmarkModel,
    detectorConf: detectorConf,
    palmNmsIou: palmNmsIou,
    palmRoiScale: palmRoiScale,
    maxDetections: maxDetections,
    minLandmarkScore: minLandmarkScore,
    enableTracking: enableTracking,
    trackingConfig: trackingConfig,
    interpreterPoolSize: effectivePoolSize,
    performanceConfig: performanceConfig,
    enableGestures: enableGestures,
    gestureMinConfidence: gestureMinConfidence,
    useCompiledModel: useCompiledModel,
    accelerators: accelerators,
    precision: precision,
  );
}