Updated iOS hand landmarker to use refactored vision task runner
This commit is contained in:
		
							parent
							
								
									020ca5eb77
								
							
						
					
					
						commit
						188321ace4
					
				| 
						 | 
				
			
			@ -66,7 +66,7 @@ objc_library(
 | 
			
		|||
        "//mediapipe/tasks/ios/core:MPPTaskInfo",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/core:MPPImage",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/core:MPPVisionPacketCreator",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/core:MPPVisionTaskRunner",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/core:MPPVisionTaskRunnerRefactored",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/hand_landmarker/utils:MPPHandLandmarkerOptionsHelpers",
 | 
			
		||||
        "//mediapipe/tasks/ios/vision/hand_landmarker/utils:MPPHandLandmarkerResultHelpers",
 | 
			
		||||
    ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@
 | 
			
		|||
#import "mediapipe/tasks/ios/common/utils/sources/NSString+Helpers.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/core/sources/MPPTaskInfo.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/core/sources/MPPVisionPacketCreator.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/core/sources/MPPVisionTaskRunner.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/core/sources/MPPVisionTaskRunnerRefactored.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/hand_landmarker/sources/MPPHandLandmarksConnections.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/hand_landmarker/utils/sources/MPPHandLandmarkerOptions+Helpers.h"
 | 
			
		||||
#import "mediapipe/tasks/ios/vision/hand_landmarker/utils/sources/MPPHandLandmarkerResult+Helpers.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +53,16 @@ static NSString *const kTaskName = @"handLandmarker";
 | 
			
		|||
    }                                                       \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define HandLandmarkerResultWithOutputPacketMap(outputPacketMap)                                   \
 | 
			
		||||
  {                                                                                                \
 | 
			
		||||
    [MPPHandLandmarkerResult                                                                       \
 | 
			
		||||
        handLandmarkerResultWithLandmarksPacket:outputPacketMap[kLandmarksOutStreamName.cppString] \
 | 
			
		||||
                           worldLandmarksPacket:outputPacketMap[kWorldLandmarksOutStreamName       \
 | 
			
		||||
                                                                    .cppString]                    \
 | 
			
		||||
                               handednessPacket:outputPacketMap[kHandednessOutStreamName           \
 | 
			
		||||
                                                                    .cppString]]                   \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@interface MPPHandLandmarker () {
 | 
			
		||||
  /** iOS Vision Task Runner */
 | 
			
		||||
  MPPVisionTaskRunner *_visionTaskRunner;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,50 +73,7 @@ static NSString *const kTaskName = @"handLandmarker";
 | 
			
		|||
 | 
			
		||||
@implementation MPPHandLandmarker
 | 
			
		||||
 | 
			
		||||
- (nullable MPPHandLandmarkerResult *)handLandmarkerResultWithOutputPacketMap:
 | 
			
		||||
    (PacketMap &)outputPacketMap {
 | 
			
		||||
  return [MPPHandLandmarkerResult
 | 
			
		||||
      handLandmarkerResultWithLandmarksPacket:outputPacketMap[kLandmarksOutStreamName.cppString]
 | 
			
		||||
                         worldLandmarksPacket:outputPacketMap[kWorldLandmarksOutStreamName
 | 
			
		||||
                                                                  .cppString]
 | 
			
		||||
                             handednessPacket:outputPacketMap[kHandednessOutStreamName.cppString]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)processLiveStreamResult:(absl::StatusOr<PacketMap>)liveStreamResult {
 | 
			
		||||
  if (![self.handLandmarkerLiveStreamDelegate
 | 
			
		||||
          respondsToSelector:@selector(handLandmarker:
 | 
			
		||||
                                 didFinishDetectionWithResult:timestampInMilliseconds:error:)]) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  NSError *callbackError = nil;
 | 
			
		||||
  if (![MPPCommonUtils checkCppError:liveStreamResult.status() toError:&callbackError]) {
 | 
			
		||||
    dispatch_async(_callbackQueue, ^{
 | 
			
		||||
      [self.handLandmarkerLiveStreamDelegate handLandmarker:self
 | 
			
		||||
                               didFinishDetectionWithResult:nil
 | 
			
		||||
                                    timestampInMilliseconds:Timestamp::Unset().Value()
 | 
			
		||||
                                                      error:callbackError];
 | 
			
		||||
    });
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PacketMap &outputPacketMap = liveStreamResult.value();
 | 
			
		||||
  if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  MPPHandLandmarkerResult *result = [self handLandmarkerResultWithOutputPacketMap:outputPacketMap];
 | 
			
		||||
 | 
			
		||||
  NSInteger timeStampInMilliseconds =
 | 
			
		||||
      outputPacketMap[kImageOutStreamName.cppString].Timestamp().Value() /
 | 
			
		||||
      kMicroSecondsPerMilliSecond;
 | 
			
		||||
  dispatch_async(_callbackQueue, ^{
 | 
			
		||||
    [self.handLandmarkerLiveStreamDelegate handLandmarker:self
 | 
			
		||||
                             didFinishDetectionWithResult:result
 | 
			
		||||
                                  timestampInMilliseconds:timeStampInMilliseconds
 | 
			
		||||
                                                    error:callbackError];
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
#pragma mark - Public
 | 
			
		||||
 | 
			
		||||
- (instancetype)initWithOptions:(MPPHandLandmarkerOptions *)options error:(NSError **)error {
 | 
			
		||||
  self = [super init];
 | 
			
		||||
| 
						 | 
				
			
			@ -152,11 +119,14 @@ static NSString *const kTaskName = @"handLandmarker";
 | 
			
		|||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _visionTaskRunner =
 | 
			
		||||
        [[MPPVisionTaskRunner alloc] initWithCalculatorGraphConfig:[taskInfo generateGraphConfig]
 | 
			
		||||
    _visionTaskRunner = [[MPPVisionTaskRunner alloc] initWithTaskInfo:taskInfo
 | 
			
		||||
                                                          runningMode:options.runningMode
 | 
			
		||||
                                                           roiAllowed:NO
 | 
			
		||||
                                                      packetsCallback:std::move(packetsCallback)
 | 
			
		||||
                                                 imageInputStreamName:kImageInStreamName
 | 
			
		||||
                                              normRectInputStreamName:kNormRectInStreamName
 | 
			
		||||
                                                                error:error];
 | 
			
		||||
 | 
			
		||||
    if (!_visionTaskRunner) {
 | 
			
		||||
      return nil;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -172,93 +142,29 @@ static NSString *const kTaskName = @"handLandmarker";
 | 
			
		|||
  return [self initWithOptions:options error:error];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (nullable MPPHandLandmarkerResult *)handLandmarkerResultWithOptionalOutputPacketMap:
 | 
			
		||||
    (std::optional<PacketMap> &)outputPacketMap {
 | 
			
		||||
  if (!outputPacketMap.has_value()) {
 | 
			
		||||
    return nil;
 | 
			
		||||
  }
 | 
			
		||||
  MPPHandLandmarkerResult *result =
 | 
			
		||||
      [self handLandmarkerResultWithOutputPacketMap:outputPacketMap.value()];
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (nullable MPPHandLandmarkerResult *)detectInImage:(MPPImage *)image error:(NSError **)error {
 | 
			
		||||
  std::optional<NormalizedRect> rect =
 | 
			
		||||
      [_visionTaskRunner normalizedRectWithImageOrientation:image.orientation
 | 
			
		||||
                                                  imageSize:CGSizeMake(image.width, image.height)
 | 
			
		||||
                                                      error:error];
 | 
			
		||||
  if (!rect.has_value()) {
 | 
			
		||||
    return nil;
 | 
			
		||||
  }
 | 
			
		||||
  std::optional<PacketMap> outputPacketMap = [_visionTaskRunner processImage:image error:error];
 | 
			
		||||
 | 
			
		||||
  Packet imagePacket = [MPPVisionPacketCreator createPacketWithMPPImage:image error:error];
 | 
			
		||||
  if (imagePacket.IsEmpty()) {
 | 
			
		||||
    return nil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Packet normalizedRectPacket =
 | 
			
		||||
      [MPPVisionPacketCreator createPacketWithNormalizedRect:rect.value()];
 | 
			
		||||
 | 
			
		||||
  PacketMap inputPacketMap = InputPacketMap(imagePacket, normalizedRectPacket);
 | 
			
		||||
 | 
			
		||||
  std::optional<PacketMap> outputPacketMap = [_visionTaskRunner processImagePacketMap:inputPacketMap
 | 
			
		||||
                                                                                error:error];
 | 
			
		||||
  return [self handLandmarkerResultWithOptionalOutputPacketMap:outputPacketMap];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (std::optional<PacketMap>)inputPacketMapWithMPPImage:(MPPImage *)image
 | 
			
		||||
                               timestampInMilliseconds:(NSInteger)timestampInMilliseconds
 | 
			
		||||
                                                 error:(NSError **)error {
 | 
			
		||||
  std::optional<NormalizedRect> rect =
 | 
			
		||||
      [_visionTaskRunner normalizedRectWithImageOrientation:image.orientation
 | 
			
		||||
                                                  imageSize:CGSizeMake(image.width, image.height)
 | 
			
		||||
                                                      error:error];
 | 
			
		||||
  if (!rect.has_value()) {
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Packet imagePacket = [MPPVisionPacketCreator createPacketWithMPPImage:image
 | 
			
		||||
                                                timestampInMilliseconds:timestampInMilliseconds
 | 
			
		||||
                                                                  error:error];
 | 
			
		||||
  if (imagePacket.IsEmpty()) {
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Packet normalizedRectPacket =
 | 
			
		||||
      [MPPVisionPacketCreator createPacketWithNormalizedRect:rect.value()
 | 
			
		||||
                                     timestampInMilliseconds:timestampInMilliseconds];
 | 
			
		||||
 | 
			
		||||
  PacketMap inputPacketMap = InputPacketMap(imagePacket, normalizedRectPacket);
 | 
			
		||||
  return inputPacketMap;
 | 
			
		||||
  return [MPPHandLandmarker handLandmarkerResultWithOptionalOutputPacketMap:outputPacketMap];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (nullable MPPHandLandmarkerResult *)detectInVideoFrame:(MPPImage *)image
 | 
			
		||||
                                 timestampInMilliseconds:(NSInteger)timestampInMilliseconds
 | 
			
		||||
                                                   error:(NSError **)error {
 | 
			
		||||
  std::optional<PacketMap> inputPacketMap = [self inputPacketMapWithMPPImage:image
 | 
			
		||||
  std::optional<PacketMap> outputPacketMap =
 | 
			
		||||
      [_visionTaskRunner processVideoFrame:image
 | 
			
		||||
                   timestampInMilliseconds:timestampInMilliseconds
 | 
			
		||||
                                     error:error];
 | 
			
		||||
  if (!inputPacketMap.has_value()) {
 | 
			
		||||
    return nil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::optional<PacketMap> outputPacketMap =
 | 
			
		||||
      [_visionTaskRunner processVideoFramePacketMap:inputPacketMap.value() error:error];
 | 
			
		||||
 | 
			
		||||
  return [self handLandmarkerResultWithOptionalOutputPacketMap:outputPacketMap];
 | 
			
		||||
  return [MPPHandLandmarker handLandmarkerResultWithOptionalOutputPacketMap:outputPacketMap];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (BOOL)detectAsyncInImage:(MPPImage *)image
 | 
			
		||||
    timestampInMilliseconds:(NSInteger)timestampInMilliseconds
 | 
			
		||||
                      error:(NSError **)error {
 | 
			
		||||
  std::optional<PacketMap> inputPacketMap = [self inputPacketMapWithMPPImage:image
 | 
			
		||||
  return [_visionTaskRunner processLiveStreamImage:image
 | 
			
		||||
                           timestampInMilliseconds:timestampInMilliseconds
 | 
			
		||||
                                             error:error];
 | 
			
		||||
  if (!inputPacketMap.has_value()) {
 | 
			
		||||
    return NO;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return [_visionTaskRunner processLiveStreamPacketMap:inputPacketMap.value() error:error];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
+ (NSArray<MPPConnection *> *)handPalmConnections {
 | 
			
		||||
| 
						 | 
				
			
			@ -285,4 +191,51 @@ static NSString *const kTaskName = @"handLandmarker";
 | 
			
		|||
  return MPPHandConnections;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark - Private
 | 
			
		||||
 | 
			
		||||
- (void)processLiveStreamResult:(absl::StatusOr<PacketMap>)liveStreamResult {
 | 
			
		||||
  if (![self.handLandmarkerLiveStreamDelegate
 | 
			
		||||
          respondsToSelector:@selector(handLandmarker:
 | 
			
		||||
                                 didFinishDetectionWithResult:timestampInMilliseconds:error:)]) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  NSError *callbackError = nil;
 | 
			
		||||
  if (![MPPCommonUtils checkCppError:liveStreamResult.status() toError:&callbackError]) {
 | 
			
		||||
    dispatch_async(_callbackQueue, ^{
 | 
			
		||||
      [self.handLandmarkerLiveStreamDelegate handLandmarker:self
 | 
			
		||||
                               didFinishDetectionWithResult:nil
 | 
			
		||||
                                    timestampInMilliseconds:Timestamp::Unset().Value()
 | 
			
		||||
                                                      error:callbackError];
 | 
			
		||||
    });
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PacketMap &outputPacketMap = liveStreamResult.value();
 | 
			
		||||
  if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  MPPHandLandmarkerResult *result = HandLandmarkerResultWithOutputPacketMap(outputPacketMap);
 | 
			
		||||
 | 
			
		||||
  NSInteger timeStampInMilliseconds =
 | 
			
		||||
      outputPacketMap[kImageOutStreamName.cppString].Timestamp().Value() /
 | 
			
		||||
      kMicroSecondsPerMilliSecond;
 | 
			
		||||
  dispatch_async(_callbackQueue, ^{
 | 
			
		||||
    [self.handLandmarkerLiveStreamDelegate handLandmarker:self
 | 
			
		||||
                             didFinishDetectionWithResult:result
 | 
			
		||||
                                  timestampInMilliseconds:timeStampInMilliseconds
 | 
			
		||||
                                                    error:callbackError];
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
+ (nullable MPPHandLandmarkerResult *)handLandmarkerResultWithOptionalOutputPacketMap:
 | 
			
		||||
    (std::optional<PacketMap> &)outputPacketMap {
 | 
			
		||||
  if (!outputPacketMap.has_value()) {
 | 
			
		||||
    return nil;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return HandLandmarkerResultWithOutputPacketMap(outputPacketMap.value());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user