คู่มือการตรวจหาจุดสังเกตของมือสำหรับ iOS

งาน MediaPipe Hand Outdoorer จะช่วยให้คุณตรวจจับจุดสังเกตของมือในรูปภาพได้ คำแนะนำเหล่านี้จะแสดงวิธีใช้ Handจุดสังเกตกับแอป iOS ตัวอย่างโค้ดที่อธิบายไว้ในวิธีการเหล่านี้จะอยู่ใน GitHub

ดูข้อมูลเพิ่มเติมเกี่ยวกับความสามารถ โมเดล และตัวเลือกการกำหนดค่าของงานนี้ได้ที่ภาพรวม

ตัวอย่างโค้ด

โค้ดตัวอย่างงาน MediaPipe Tasks เป็นการติดตั้งใช้งานขั้นพื้นฐานของแอป Hand Lander สำหรับ iOS ตัวอย่างนี้ใช้กล้องบนอุปกรณ์ iOS เพื่อตรวจจับจุดสังเกตของมือในสตรีมวิดีโอต่อเนื่อง แอปยังตรวจหาจุดสังเกตของ มือในรูปภาพและวิดีโอจากแกลเลอรีของอุปกรณ์ได้ด้วย

คุณสามารถใช้แอปเป็นจุดเริ่มต้นสำหรับแอป iOS ของคุณเองหรือใช้อ้างอิงเมื่อแก้ไขแอปที่มีอยู่ โค้ดตัวอย่างของ Hand Marker นั้นโฮสต์อยู่ใน GitHub

ดาวน์โหลดโค้ด

วิธีการต่อไปนี้แสดงวิธีสร้างสำเนาโค้ดตัวอย่างในเครื่องโดยใช้เครื่องมือบรรทัดคำสั่ง git

วิธีดาวน์โหลดโค้ดตัวอย่าง

  1. โคลนที่เก็บ Git โดยใช้คำสั่งต่อไปนี้

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. คุณสามารถกำหนดค่าอินสแตนซ์ git เพื่อใช้การชำระเงินแบบกระจัดกระจาย เพื่อให้คุณมีเฉพาะไฟล์สำหรับแอปตัวอย่าง Handจุดสังเกต ดังนี้

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

หลังจากสร้างโค้ดตัวอย่างเวอร์ชันในเครื่องแล้ว คุณจะติดตั้งไลบรารีงาน MediaPipe แล้วเปิดโปรเจ็กต์โดยใช้ Xcode และเรียกใช้แอป ดูวิธีได้ที่คู่มือการตั้งค่าสำหรับ iOS

องค์ประกอบหลัก

ไฟล์ต่อไปนี้มีโค้ดสำคัญสำหรับแอปพลิเคชันตัวอย่าง Hand Marker:

  • HandLandmarkerService.swift: เริ่มต้น Handจุดสังเกต จัดการการเลือกโมเดล และทำการอนุมานข้อมูลอินพุต
  • CameraViewController.swift: ใช้ UI สำหรับโหมดป้อนข้อมูลฟีดกล้องแบบสดและแสดงภาพผลลัพธ์
  • MediaLibraryViewController.swift: ใช้ UI สำหรับโหมดป้อนข้อมูลภาพนิ่งและไฟล์วิดีโอ และแสดงภาพผลลัพธ์

ตั้งค่า

ส่วนนี้จะอธิบายขั้นตอนสำคัญในการตั้งค่าสภาพแวดล้อมการพัฒนาและโปรเจ็กต์โค้ดเพื่อใช้ Handจุดสังเกต ดูข้อมูลทั่วไปเกี่ยวกับการตั้งค่าสภาพแวดล้อมการพัฒนาสำหรับการใช้งาน MediaPipe รวมถึงข้อกำหนดเวอร์ชันแพลตฟอร์มได้ที่คู่มือการตั้งค่าสำหรับ iOS

การอ้างอิง

Handจุดสังเกตใช้ไลบรารี MediaPipeTasksVision ซึ่งต้องติดตั้งโดยใช้ CocoaPods ไลบรารีนี้ใช้งานได้กับทั้งแอป Swift และ Objective-C และไม่จำเป็นต้องมีการตั้งค่าเฉพาะภาษาใดๆ เพิ่มเติม

หากต้องการดูวิธีการติดตั้ง CocoaPods ใน macOS โปรดอ่านคู่มือการติดตั้ง CocoaPods ดูวิธีสร้าง Podfile ด้วยพ็อดที่จำเป็นสำหรับแอปได้ที่การใช้ CocoaPods

เพิ่มพ็อด MediaPipeTasksVision ใน Podfile โดยใช้โค้ดต่อไปนี้

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

หากแอปมีเป้าหมายการทดสอบหน่วย โปรดอ่านคู่มือการตั้งค่าสำหรับ iOS เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่า Podfile

รุ่น

งาน MediaPipe Hand Marker ต้องใช้โมเดลที่ผ่านการฝึกซึ่งเข้ากันได้กับงานนี้ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่ผ่านการฝึกที่พร้อมใช้งานสำหรับ จุดสังเกตของมือ ให้ดูที่ภาพรวมงานส่วน โมเดล

เลือกและดาวน์โหลดโมเดล แล้วเพิ่มลงในไดเรกทอรีโปรเจ็กต์โดยใช้ Xcode สำหรับคำแนะนำเกี่ยวกับวิธีเพิ่มไฟล์ลงในโปรเจ็กต์ Xcode โปรดดูการจัดการไฟล์และโฟลเดอร์ในโปรเจ็กต์ Xcode

ใช้พร็อพเพอร์ตี้ BaseOptions.modelAssetPath เพื่อระบุเส้นทางไปยังโมเดลใน App Bundle โปรดดูตัวอย่างโค้ดในส่วนถัดไป

สร้างงาน

คุณสามารถสร้างงาน Hand Marker โดยการเรียกหนึ่งในโปรแกรมเริ่มต้น เครื่องมือเริ่มต้น HandLandmarker(options:) จะยอมรับค่าสำหรับตัวเลือกการกำหนดค่า

หากคุณไม่ต้องการใช้มือจุดสังเกตที่เริ่มต้นด้วยตัวเลือกการกำหนดค่าที่กำหนดเอง คุณสามารถใช้เครื่องมือเริ่มต้น HandLandmarker(modelPath:) เพื่อสร้างจุดสังเกตสำหรับมือที่มีตัวเลือกเริ่มต้น ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการกำหนดค่าได้ที่ภาพรวมการกำหนดค่า

งาน Handจุดสังเกตรองรับข้อมูลอินพุต 3 ประเภท ได้แก่ ภาพนิ่ง ไฟล์วิดีโอ และสตรีมวิดีโอสด โดยค่าเริ่มต้น HandLandmarker(modelPath:) จะเริ่มต้นงาน สำหรับภาพนิ่ง หากต้องการเริ่มต้นงานเพื่อประมวลผลไฟล์วิดีโอหรือสตรีมวิดีโอสด ให้ใช้ HandLandmarker(options:) เพื่อระบุโหมดการทำงานของวิดีโอหรือสตรีมแบบสด โหมดสตรีมแบบสดยังต้องใช้ตัวเลือกการกำหนดค่า handLandmarkerLiveStreamDelegate เพิ่มเติมด้วย ซึ่งช่วยให้ตัวทำเครื่องหมายมือส่งผลลัพธ์ที่เป็นจุดสังเกตด้วยมือไปยังผู้รับมอบสิทธิ์แบบไม่พร้อมกัน

เลือกแท็บที่เหมาะกับโหมดการวิ่งของคุณเพื่อดูวิธีสร้างงานและใช้การอนุมาน

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 ตั้งค่าโหมดการทำงาน มี 3 โหมดดังนี้

IMAGE: โหมดสำหรับการป้อนข้อมูลรูปภาพเดียว

วิดีโอ: โหมดสำหรับเฟรมที่ถอดรหัสของวิดีโอ

LIVE_Stream: โหมดสำหรับสตรีมแบบสดของข้อมูลอินพุต เช่น จากกล้อง ในโหมดนี้ ต้องมีการเรียกใช้ resultsListener เพื่อตั้งค่า Listener เพื่อรับผลลัพธ์แบบไม่พร้อมกัน ในโหมดนี้ คุณต้องตั้งค่า 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 คะแนนความเชื่อมั่นขั้นต่ำสำหรับการติดตามมือจะถือว่าประสบความสำเร็จ นี่คือเกณฑ์ IoU ของกรอบล้อมรอบระหว่างมือในเฟรมปัจจุบันและเฟรมสุดท้าย ในโหมดวิดีโอและโหมดสตรีมของมือจุดสังเกต หากติดตามไม่สำเร็จ จุดสังเกตของมือจะทริกเกอร์การตรวจจับมือ มิฉะนั้นระบบจะข้ามการตรวจจับมือ 0.0 - 1.0 0.5
result_listener ตั้งค่า Listener ผลลัพธ์ให้รับผลการตรวจจับแบบอะซิงโครนัสเมื่อตัวทำเครื่องหมายสำหรับมืออยู่ในโหมดสตรีมแบบสด ใช้ได้เมื่อตั้งค่าโหมดทำงานเป็น LIVE_STREAM เท่านั้น ไม่มีข้อมูล ไม่มีข้อมูล

เมื่อตั้งค่าโหมดวิ่งเป็นสตรีมแบบสด เครื่องมือจุดสังเกตของมือถือจะต้องใช้ตัวเลือกการกำหนดค่า handLandmarkerLiveStreamDelegate เพิ่มเติม ซึ่งจะทำให้เครื่องมือจุดสังเกตของแฮนด์แสดงผลในการตรวจจับจุดสังเกตแบบไม่พร้อมกัน ผู้ได้รับมอบสิทธิ์ต้องใช้เมธอด handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) ซึ่ง Handlandser เรียกใช้หลังจากประมวลผลผลการตรวจจับจุดสังเกตสำหรับแต่ละเฟรม

ชื่อตัวเลือก คำอธิบาย ช่วงของค่า ค่าเริ่มต้น
handLandmarkerLiveStreamDelegate เปิดใช้ Hand Marker เพื่อรับผลการตรวจจับจุดสังเกตของมือแบบไม่พร้อมกันในโหมดสตรีมแบบสด คลาสที่มีการตั้งค่าอินสแตนซ์เป็นพร็อพเพอร์ตี้นี้ต้องใช้เมธอด handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) ไม่เกี่ยวข้อง ไม่ได้ตั้งค่า

เตรียมข้อมูล

คุณต้องแปลงรูปภาพหรือเฟรมอินพุตเป็นวัตถุ MPImage ก่อนที่จะส่งผ่านไปยังเครื่องมือจุดสังเกตด้วยมือ MPImage รองรับรูปแบบรูปภาพ iOS ประเภทต่างๆ และสามารถใช้ในโหมดการอนุมานได้ทุกโหมด ดูข้อมูลเพิ่มเติมเกี่ยวกับ MPImage ได้ที่ MPImage API

เลือกรูปแบบรูปภาพ iOS ตามกรณีการใช้งานและโหมดที่แอปพลิเคชันต้องการMPImage ยอมรับรูปแบบรูปภาพ UIImage, CVPixelBuffer และ CMSampleBuffer บน iOS

UIImage

รูปแบบ UIImage เหมาะสมสำหรับโหมดการวิ่งต่อไปนี้

  • รูปภาพ: รูปภาพจาก App Bundle แกลเลอรีของผู้ใช้ หรือระบบไฟล์ที่จัดรูปแบบเป็นรูปภาพ 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 ที่รองรับค่าใดก็ได้ จุดสังเกตของมือไม่รองรับการวางแนวแบบมิเรอร์ เช่น .upMirrored, .downMirrored, .leftMirrored, .rightMirrored

ดูข้อมูลเพิ่มเติมเกี่ยวกับ UIImage ได้ในเอกสารประกอบสำหรับนักพัฒนาแอปของ Apple สำหรับ UIImage

CVPixelBuffer

รูปแบบ CVPixelBuffer เหมาะกับแอปพลิเคชันที่สร้างเฟรมและใช้เฟรมเวิร์ก CoreImage ของ iOS สำหรับการประมวลผล

รูปแบบ CVPixelBuffer เหมาะสมสำหรับโหมดการวิ่งต่อไปนี้

  • รูปภาพ: แอปที่สร้างรูปภาพ CVPixelBuffer รูปหลังจากการประมวลผลบางส่วนโดยใช้เฟรมเวิร์ก CoreImage ของ iOS สามารถส่งไปยัง Hand Marker ในโหมดแสดงภาพได้

  • วิดีโอ: เฟรมวิดีโอสามารถแปลงเป็นรูปแบบ 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 โดย iOS AVCaptureVideoDataOutput

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 โปรดดูเอกสารสำหรับ นักพัฒนาซอฟต์แวร์ CMSampleBuffer

เรียกใช้งาน

หากต้องการเรียกใช้ Handจุดสังเกต ให้ใช้เมธอด 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];
    

ตัวอย่างโค้ดจุดสังเกตของแฮนด์จะแสดงการใช้งานของแต่ละโหมดอย่างละเอียด โค้ดตัวอย่างช่วยให้ผู้ใช้สลับโหมดการประมวลผลได้ ซึ่ง อาจไม่จำเป็นสำหรับกรณีการใช้งานของคุณ

โปรดทราบดังต่อไปนี้

  • เมื่อเรียกใช้ในโหมดวิดีโอหรือโหมดสตรีมแบบสด คุณต้องระบุการประทับเวลาของเฟรมอินพุตในงานมือจุดสังเกตด้วย

  • เมื่อเรียกใช้ในโหมดรูปภาพหรือวิดีโอ งาน Handจุดสังเกตจะบล็อกเทรดปัจจุบันจนกว่าจะประมวลผลรูปภาพหรือเฟรมอินพุตเสร็จ หากต้องการหลีกเลี่ยงการบล็อกเทรดปัจจุบัน ให้ประมวลผลการประมวลผลในเทรดเบื้องหลังโดยใช้เฟรม iOS Dispatch หรือ NSOperation

  • เมื่อทำงานในโหมดสตรีมแบบสด งาน Handจุดสังเกตจะส่งคืนทันที และจะไม่บล็อกเทรดปัจจุบัน โดยจะเรียกใช้เมธอด handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) ด้วยผลลัพธ์เครื่องมือทำเครื่องหมายด้วยมือหลังจากประมวลผลเฟรมอินพุตแต่ละเฟรม Handจุดสังเกตจะเรียกใช้เมธอดนี้แบบไม่พร้อมกันในคิวการจัดส่งแบบอนุกรมที่เฉพาะเจาะจง สำหรับการแสดงผลลัพธ์บนอินเทอร์เฟซผู้ใช้ ให้ส่งผลลัพธ์ไปยังคิวหลักหลังจากประมวลผลผลลัพธ์แล้ว หากมีการเรียกฟังก์ชัน detectAsync เมื่องานแฮนด์แลนด์มาร์กกำลังยุ่งกับการประมวลผลอีกเฟรมหนึ่ง จุดสังเกตของมือจะไม่สนใจเฟรมอินพุตใหม่

แฮนเดิลและแสดงผลลัพธ์

เมื่อเรียกใช้การอนุมาน งาน HandจุดสังเกตจะแสดงHandLandmarkerResultซึ่งมีจุดสังเกตของมือในพิกัดรูปภาพ จุดสังเกตของมือในพิกัดของโลกและความถนัดของมือ(ซ้าย/ขวา) ของมือที่ตรวจพบ

ตัวอย่างต่อไปนี้แสดงตัวอย่างข้อมูลเอาต์พุตจากงานนี้

เอาต์พุต HandLandmarkerResult มีคอมโพเนนต์ 3 คอมโพเนนต์ แต่ละคอมโพเนนต์คืออาร์เรย์ โดยแต่ละองค์ประกอบจะมีผลดังต่อไปนี้สำหรับมือที่ตรวจพบเพียงข้างเดียว

  • ความถนัดของมือ

    ความถนัดของมือแสดงให้เห็นว่ามือที่ตรวจพบเป็นมือซ้ายหรือมือขวา

  • จุดสังเกต

    มีจุดสังเกต 21 จุด แต่ละจุดประกอบด้วยพิกัด x, y และ z ระบบจะปรับพิกัด x และ y ให้เป็นมาตรฐานเป็น [0.0, 1.0] ตามความกว้างและความสูงของรูปภาพตามลำดับ พิกัด z แสดงถึงความลึกของจุดสังเกต โดยความลึกที่ข้อมือเป็นต้นทาง ค่ายิ่งน้อยเท่าไหร่ จุดสังเกตก็จะใกล้เคียงกับกล้องมากขึ้น ขนาดของ z ใช้สเกลใกล้เคียงกับ x

  • สถานที่สำคัญของโลก

    นอกจากนี้ยังมีจุดสังเกต 21 จุดในพิกัดของโลกด้วย จุดสังเกตแต่ละรายการประกอบด้วย x, y และ z ซึ่งแสดงพิกัด 3 มิติในชีวิตจริงในหน่วยเมตรที่มีจุดเริ่มต้นอยู่ที่จุดศูนย์กลางเรขาคณิตของมือ

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)

รูปภาพต่อไปนี้แสดงภาพเอาต์พุตของงาน