دليل التعرّف على المعالم يدويًا في نظام التشغيل iOS

تتيح لك مهمة MediaPipe Handmarker اكتشاف معالم الأيدي في الصورة. توضح لك هذه التعليمات كيفية استخدام أداة جذب اليد مع تطبيقات iOS. يتوفر عينة التعليمات البرمجية الموضحة في هذه التعليمات على GitHub.

للحصول على مزيد من المعلومات حول الإمكانيات والنماذج وخيارات الإعداد لهذه المهمة، يُرجى الاطّلاع على نظرة عامة.

مثال الرمز البرمجي

يُعد مثال الرمز البرمجي لمهام MediaPipe تطبيقًا أساسيًا لتطبيق موجودة في مؤشر اليد لنظام التشغيل iOS. يستخدم المثال الكاميرا على جهاز iOS فعلي لرصد المعالم اليدية في بث فيديو مستمر. يمكن للتطبيق أيضًا اكتشاف معالم اليد في الصور والفيديوهات من معرض الجهاز.

يمكنك استخدام التطبيق كنقطة بداية لتطبيق iOS الخاص بك، أو الرجوع إليه عند تعديل تطبيق حالي. تتم استضافة مثال الرمز البرمجي لتطبيق Hand إصلاحer على GitHub.

تنزيل الرمز

توضّح لك التعليمات التالية كيفية إنشاء نسخة محلية من رمز المثال باستخدام أداة سطر الأوامر git.

لتنزيل نموذج الرمز:

  1. استنسِخ مستودع git باستخدام الأمر التالي:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. اختياريًا، اضبط مثيل git لاستخدام عملية الدفع المتفرقة، بحيث لا يكون لديك سوى ملفات تطبيق نموذج git النموذج:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/hand_landmarker/ios/
    

بعد إنشاء نسخة محلية من نموذج الرمز، يمكنك تثبيت مكتبة مهام MediaPipe، وفتح المشروع باستخدام Xcode، وتشغيل التطبيق. وللحصول على التعليمات، يمكنك الاطّلاع على دليل الإعداد لنظام التشغيل iOS.

المكونات الرئيسية

تحتوي الملفات التالية على التعليمات البرمجية الهامة لتطبيق مثال Handيهاer:

  • HandLandmarkerService.swift: تعمل هذه الميزة على إعداد أداة مَعلم مؤشر اليد ومعالجة اختيار النموذج وإجراء الاستنتاجات على بيانات الإدخال.
  • CameraViewController.swift: تنفِّذ هذه الميزة واجهة المستخدم في وضع الإدخال الخاص بخلاصة الكاميرا المباشرة وتعرض النتائج.
  • MediaLibraryViewController.swift: ينفّذ هذا الأسلوب واجهة المستخدم في وضع إدخال ملفات الفيديو والصور الثابتة، ويعرض النتائج.

ضبط إعدادات الجهاز

يصف هذا القسم الخطوات الرئيسية لإعداد بيئة التطوير الخاصة بك ومشروعات التعليمات البرمجية لاستخدام أداة الجذب في الأداة. للحصول على معلومات عامة حول إعداد بيئة التطوير لاستخدام مهام MediaPipe، بما في ذلك متطلبات إصدار النظام الأساسي، يُرجى الاطّلاع على دليل الإعداد لنظام التشغيل iOS.

التبعيات

تستخدم أداة جذب الاهتمام مكتبة MediaPipeTasksVision التي يجب تثبيتها باستخدام CocoaPods. المكتبة متوافقة مع كل من تطبيقَي Swift وObjective-C ولا تتطلب أي إعداد إضافي خاص بلغة معيّنة.

للحصول على تعليمات حول تثبيت CocoaPods على نظام التشغيل macOS، يُرجى الرجوع إلى دليل تثبيت CocoaPods. للحصول على تعليمات حول كيفية إنشاء Podfile مع مجموعات الإعلانات المتسلسلة اللازمة لتطبيقك، يمكنك الاطّلاع على المقالة استخدام CocoaPods.

أضِف مجموعة MediaPipeTasksVision في Podfile باستخدام الرمز التالي:

target 'MyHandLandmarkerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

إذا كان تطبيقك يتضمّن أهداف اختبار الوحدات، يُرجى الرجوع إلى دليل الإعداد لنظام التشغيل iOS للحصول على معلومات إضافية حول إعداد Podfile.

الطراز

تتطلب مهمة MediaPipe Handmarker نموذجًا مدرَّبًا متوافقًا مع هذه المهمة. لمزيد من المعلومات حول النماذج المدربة المتاحة من أجل أداة Handmarker، راجع قسم النظرة العامة على المهمة في قسم النماذج.

حدد نموذجًا ونزّله وأضفه إلى دليل المشروع باستخدام Xcode. للحصول على تعليمات حول كيفية إضافة ملفات إلى مشروع Xcode، يمكنك الرجوع إلى إدارة الملفات والمجلدات في مشروع Xcode.

استخدِم السمة BaseOptions.modelAssetPath لتحديد المسار إلى النموذج في حِزمة التطبيق. للاطّلاع على مثال على الرمز البرمجي، راجِع القسم التالي.

إنشاء المهمة

يمكنك إنشاء مهمة محدد اليد عن طريق استدعاء أحد مقدماتها. يقبل مبدئي HandLandmarker(options:) القيم لخيارات الضبط.

إذا لم تكن بحاجة إلى تهيئة أداة مَعلمة يدويًا باستخدام خيارات ضبط مخصّصة، يمكنك استخدام أداة الإعداد HandLandmarker(modelPath:) لإنشاء أداة "أداة مَعلمة" بالخيارات التلقائية. لمزيد من المعلومات حول خيارات الضبط، يُرجى الاطّلاع على نظرة عامة على الإعدادات.

تتوافق مَهمّة أداة "معالم اليد" مع 3 أنواع من بيانات الإدخال، وهي الصور الثابتة وملفات الفيديو وأحداث الفيديو التي يتم بثها مباشرةً. يبدأ HandLandmarker(modelPath:) تلقائيًا في إعداد مهمة للصور الثابتة. إذا كنت تريد إعداد مهمتك لمعالجة ملفات الفيديو أو أحداث البث المباشر، استخدِم HandLandmarker(options:) لتحديد الفيديو أو وضع تشغيل البث المباشر. يتطلب وضع البث المباشر أيضًا خيار ضبط handLandmarkerLiveStreamDelegate الإضافي، والذي يتيح لأداة "Handmarker" عرض نتائج معلمة اليد في المستخدم المفوَّض بشكل غير متزامن.

اختَر علامة التبويب المقابلة لوضع الركض لمعرفة كيفية إنشاء المهمة وتشغيل الاستنتاج.

Swift

صورة

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "hand_landmarker",
                                      ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    

حملة فيديو

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "hand_landmarker",
                                      ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    

أحداث بث مباشر

import MediaPipeTasksVision

// Class that conforms to the `HandLandmarkerLiveStreamDelegate` protocol and
// implements the method that the hand landmarker calls once it finishes
// performing landmarks detection in each input frame.
class HandLandmarkerResultProcessor: NSObject, HandLandmarkerLiveStreamDelegate {

  func handLandmarker(
    _ handLandmarker: HandLandmarker,
    didFinishDetection result: HandLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the hand landmarker result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "hand_landmarker",
  ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

// Assign an object of the class to the `handLandmarkerLiveStreamDelegate`
// property.
let processor = HandLandmarkerResultProcessor()
options.handLandmarkerLiveStreamDelegate = processor

let handLandmarker = try HandLandmarker(options: options)
    

Objective-C

صورة

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

حملة فيديو

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

أحداث بث مباشر

@import MediaPipeTasksVision;

// Class that conforms to the `MPPHandLandmarkerLiveStreamDelegate` protocol
// and implements the method that the hand landmarker calls once it finishes
// performing landmarks detection in each input frame.

@interface APPHandLandmarkerResultProcessor : NSObject 

@end

@implementation APPHandLandmarkerResultProcessor

-   (void)handLandmarker:(MPPHandLandmarker *)handLandmarker
    didFinishDetectionWithResult:(MPPHandLandmarkerResult *)handLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the hand landmarker result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

// Assign an object of the class to the `handLandmarkerLiveStreamDelegate`
// property.
APPHandLandmarkerResultProcessor *processor =
  [APPHandLandmarkerResultProcessor new];
options.handLandmarkerLiveStreamDelegate = processor;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

خيارات الضبط

تتضمّن هذه المهمة خيارات الضبط التالية لتطبيقات iOS:

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
running_mode تحدِّد هذه السياسة وضع التشغيل للمهمة. هناك ثلاثة أوضاع:

IMAGE: وضع إدخالات الصورة الفردية.

فيديو: وضع لقطات الفيديو التي تم فك ترميزها

البث المباشر: وضع بث مباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب استدعاء resultsListener لإعداد أداة معالجة الصوت لكي تتلقى النتائج بشكل غير متزامن. في هذا الوضع، يجب ضبط handLandmarkerLiveStreamDelegate على مثيل لفئة تنفّذ HandLandmarkerLiveStreamDelegate لتلقّي نتائج رصد معالِم اليد بشكل غير متزامن.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
numHands الحد الأقصى لعدد الأيدي التي يتم رصدها بواسطة أداة رصد معلَمة اليد Any integer > 0 1
minHandDetectionConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار رصد اليد ناجحًا في نموذج اكتشاف راحة اليد. 0.0 - 1.0 0.5
minHandPresenceConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة لنتيجة تواجد اليد في نموذج رصد معالِم اليد. في وضع الفيديو ووضع البث المباشر، إذا كانت نتيجة الثقة في تواجد اليد من نموذج علامات اليد أقل من هذا الحدّ، تشغّل أداة قياس راحة اليد نموذج رصد راحة اليد. وبخلاف ذلك، تحدّد خوارزمية تتبُّع بسيطة لليد موقع الأيدي من أجل رصد المعالم لاحقًا. 0.0 - 1.0 0.5
minTrackingConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار تتبُّع اليد ناجحًا. هذا هو الحدّ الأدنى لوحدات وحدات القياس بين الأيدي في الإطار الحالي والإطار الأخير. في وضع "الفيديو" ووضع "البث" في أداة قياس اليد، إذا تعذّر إتمام عملية التتبُّع، تشغّل أداة Handمجموعة ميزة "رصد اليد". وفي حال عدم تنفيذ هذا الإجراء، يتخطّى الجهاز ميزة رصد اليد. 0.0 - 1.0 0.5
result_listener يعمل هذا الإعداد على ضبط أداة معالجة النتائج لتلقّي نتائج الرصد بشكل غير متزامن عندما يكون معلَم اليد في وضع البث المباشر. لا ينطبق هذا الإجراء إلا عند ضبط وضع التشغيل على LIVE_STREAM. لا ينطبق لا ينطبق

عند ضبط وضع التشغيل على البث المباشر، تطلب أداة Hand إصلاحer خيار ضبط handLandmarkerLiveStreamDelegate الإضافي، وهو ما يتيح لأداة قياس اليد تقديم نتائج اكتشاف معالم اليد بشكل غير متزامن. على المفوَّض أن ينفّذ طريقة handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:)، التي تستدعيها أداة Hand التعليمات بعد معالجة نتائج رصد معالم اليد لكل إطار.

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
handLandmarkerLiveStreamDelegate يفعّل أداة Handlander من تلقّي نتائج رصد مؤشرات اليد بشكل غير متزامن في وضع البث المباشر. أمّا الفئة التي تم ضبط مثيلها على هذه السمة، فعليها تنفيذ الطريقة handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:). غير منطبق لم يتم الضبط.

إعداد البيانات

تحتاج إلى تحويل الصورة أو الإطار الذي تم إدخاله إلى كائن MPImage قبل تمريره إلى أداة جذب اليد. تتوافق "MPImage" مع أنواع مختلفة من تنسيقات الصور على iOS، ويمكن استخدامها في أي وضع تشغيل للاستنتاج. لمزيد من المعلومات حول MPImage، يمكنك مراجعة MPImage API

اختَر تنسيق صورة iOS استنادًا إلى حالة الاستخدام ووضع التشغيل الذي يتطلبه تطبيقك.تقبل "MPImage" تنسيقات الصور UIImage وCVPixelBuffer وCMSampleBuffer على iOS.

UIImage

يناسب تنسيق UIImage أوضاع الجري التالية:

  • الصور: صور من حِزمة تطبيق أو معرض مستخدمين أو نظام ملفات بتنسيق UIImage يمكن تحويله إلى عنصر MPImage.

  • الفيديوهات: استخدِم AVAssetImageGenerator لاستخراج إطارات الفيديو إلى تنسيق CGImage، ثم تحويلها إلى صور UIImage

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

يؤدي المثال إلى إعداد MPImage باستخدام الاتجاه التلقائي UIImage.Orientation.Up. يمكنك إعداد MPImage باستخدام أي من قيم UIImage.Orientation المتوافقة. لا يتيح تطبيق Handmarker استخدام الاتجاهات المعكوسة، مثل .upMirrored و.downMirrored و.leftMirrored و.rightMirrored.

لمزيد من المعلومات حول UIImage، يمكن الاطّلاع على مستندات مطوّري واجهة برمجة التطبيقات UIImage من Apple.

CVPixelBuffer

يناسب تنسيق CVPixelBuffer التطبيقات التي تنشئ إطارات وتستخدم إطار عمل CoreImage لنظام التشغيل iOS من أجل المعالجة.

يناسب تنسيق CVPixelBuffer أوضاع الجري التالية:

  • الصور: يمكن إرسال التطبيقات التي تنشئ صور CVPixelBuffer بعد إجراء بعض عمليات المعالجة باستخدام إطار عمل CoreImage في نظام التشغيل iOS إلى أداة Hand علامات التبويب في وضع تشغيل الصور.

  • الفيديوهات: يمكن تحويل إطارات الفيديو إلى تنسيق CVPixelBuffer لمعالجتها، ثم إرسالها بعد ذلك إلى أداة الجذب في وضع الفيديو.

  • البث المباشر: يمكن تحويل التطبيقات التي تستخدم كاميرا iOS لإنشاء إطارات إلى تنسيق CVPixelBuffer لمعالجتها قبل إرسالها إلى أداة اليد في وضع البث المباشر.

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

لمزيد من المعلومات حول CVPixelBuffer، يُرجى الاطّلاع على مستندات مطوّري برامج CVPixelBuffer Apple.

CMSampleBuffer

يخزّن تنسيق CMSampleBuffer عينات وسائط من نوع وسائط موحد، وهو مناسب تمامًا لوضع تشغيل البث المباشر. ويتم عرض الإطارات المباشرة من كاميرات iOS بالتنسيق CMSampleBuffer بشكل غير متزامن بواسطة AVCaptureVideoDataOutput في نظام التشغيل iOS.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

لمزيد من المعلومات حول CMSampleBuffer، يُرجى الاطّلاع على مستندات مطوّري البرامج الخاصة بـ CMعيّنBuffer من Apple.

تنفيذ المهمة

لتشغيل "أداة جذب اليد"، استخدِم طريقة detect() الخاصة بوضع التشغيل المحدَّد:

  • صورة ثابتة: detect(image:)
  • الفيديو: detect(videoFrame:timestampInMilliseconds:)
  • بث مباشر: detectAsync(image:timestampInMilliseconds:)

Swift

صورة

let result = try handLandmarker.detect(image: image)
    

حملة فيديو

let result = try handLandmarker.detect(
    videoFrame: image,
    timestampInMilliseconds: timestamp)
    

أحداث بث مباشر

try handLandmarker.detectAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

صورة

MPPHandLandmarkerResult *result =
  [handLandmarker detectInImage:image error:nil];
    

حملة فيديو

MPPHandLandmarkerResult *result =
  [handLandmarker detectInVideoFrame:image
             timestampInMilliseconds:timestamp
                               error:nil];
    

أحداث بث مباشر

BOOL success =
  [handLandmarker detectAsyncInImage:image
             timestampInMilliseconds:timestamp
                               error:nil];
    

يوضح مثال التعليمات البرمجية لمعالم اليد عمليات تنفيذ كل من هذه الأوضاع بمزيد من التفصيل. يسمح رمز المثال للمستخدم بالتبديل بين أوضاع المعالجة، وهو ما قد لا يكون مطلوبًا لحالة الاستخدام الخاصة بك.

يُرجى ملاحظة ما يلي:

  • عند التشغيل في وضع الفيديو أو وضع البث المباشر، يجب أيضًا تقديم الطابع الزمني لإطار الإدخال إلى مَهمّة "أداة مؤشر اليد".

  • عند التشغيل في وضع الصورة أو الفيديو، تحظر مهمة "معالم اليد" سلسلة التعليمات الحالية حتى تنتهي من معالجة الصورة أو الإطار المُدخل. لتجنُّب حظر سلسلة التعليمات الحالية، نفِّذ عملية المعالجة في سلسلة محادثات في الخلفية باستخدام إطارَي عمل Dispatch أو NSOperation في نظام التشغيل iOS.

  • عند التشغيل في وضع البث المباشر، تعود مَهمّة مؤشر اليد على الفور بدون حظر سلسلة المحادثات الحالية. يستدعي أسلوب handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) مع نتيجة معلم اليد بعد معالجة كل إطار إدخال. تستدعي أداة Hand Markdown هذه الطريقة بشكل غير متزامن في قائمة انتظار إرسال تسلسلية مخصصة. لعرض النتائج على واجهة المستخدم، قم بإرسال النتائج إلى قائمة الانتظار الرئيسية بعد معالجة النتائج. إذا تم استدعاء الدالة detectAsync عندما تكون مهمة أداة Handmarker مشغولة بمعالجة إطار آخر، يتجاهل مؤشر Hand يوجد إطار الإدخال الجديد.

التعامل مع النتائج وعرضها

عند استنتاج الاستنتاج، تعرض مَهمّة "أداة التعرّف على اليد" HandLandmarkerResult الذي يحتوي على معالم اليد في إحداثيات الصور، ومعالم اليد في إحداثيات العالم، واليد(اليد اليسرى/اليمنى) التي يتم رصدها.

ويوضح ما يلي مثالاً على بيانات المخرجات من هذه المهمة:

يحتوي ناتج HandLandmarkerResult على ثلاثة مكوّنات. كل مكوّن هو مصفوفة، حيث يحتوي كل عنصر فيها على النتائج التالية ليد واحدة تم اكتشافها:

  • الإنصاف

    تشير ميزة "استخدام اليد" إلى ما إذا كانت الأيدي التي تم رصدها هما اليد اليسرى أو اليمنى.

  • المَعالم

    هناك 21 معلمًا على اليد، يتألف كل منها من إحداثيات x وy وz. تتم تسوية إحداثيتَي x وy لتصبح [0.0 و1.0] في عرض الصورة وارتفاعها، على التوالي. يمثل التنسيق z عمق المعلم، حيث يكون العمق في المعصم هو الأصل. كلما كانت القيمة أصغر، اقترب المعلم الرئيسي من الكاميرا. يستخدم مقدار z مقياسًا مماثلاً تقريبًا لمقياس x.

  • معالم عالمية

    ويتم عرض 21 معلمًا يدويًا في الإحداثيات العالمية. ويتألف كل معلَم من x وy وz، ما يمثّل إحداثيات ثلاثية الأبعاد حقيقية بمقاييس، وتتكوّن من نقطة الأصل في المركز الهندسي لليد.

HandLandmarkerResult:
  Handedness:
    Categories #0:
      index        : 0
      score        : 0.98396
      categoryName : Left
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : -3.41E-7
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
    ... (21 landmarks for a hand)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
    ... (21 world landmarks for a hand)

تُظهر الصورة التالية تصورًا لناتج المهمة: