iOS에서 ML Kit를 사용하여 객체 감지 및 추적

ML Kit를 사용하면 연속된 동영상 프레임에서 객체를 감지하고 추적할 수 있습니다.

이미지를 ML Kit에 전달하면 이미지에서 최대 5개의 객체를 감지합니다. 이미지의 각 객체의 위치와 함께 표시됩니다. Kubernetes에서 객체를 감지할 때는 각 객체에는 객체를 추적하는 데 사용할 수 있는 고유 ID가 있습니다. 확인할 수 있습니다 선택사항으로 대략적인 객체를 사용 설정할 수도 있습니다. 광범위한 카테고리 설명으로 객체에 라벨을 지정합니다.

사용해 보기

시작하기 전에

  1. Podfile에 다음 ML Kit 포드를 포함합니다.
    pod 'GoogleMLKit/ObjectDetection', '8.0.0'
    
  2. 프로젝트의 포드를 설치하거나 업데이트한 후 포드를 사용하여 Xcode 프로젝트를 엽니다. .xcworkspace ML Kit는 Xcode 버전 12.4 이상에서 지원됩니다.

1. 객체 감지기 구성

객체를 감지하고 추적하려면 먼저 ObjectDetector하고 원하는 경우 원하는 감지기 설정을 지정합니다. 변경할 수 있습니다.

  1. 사용 사례의 객체 인식기를 다음과 같이 구성합니다. ObjectDetectorOptions 객체. 다음 항목을 변경할 수 있습니다. 설정:

    객체 감지기 설정
    감지 모드 .stream (기본값) | .singleImage

    기본값인 스트림 모드에서는 객체 인식기가 매우 낮은 빈도로 실행됩니다. 불완전한 결과 (예: 지정되지 않은 결과)를 경계 상자 또는 카테고리)을 두 가지로 나뉩니다. 또한 스트림 모드에서는 감지기가 객체에 대한 ID로, 여러 프레임에서 객체를 추적하는 데 사용할 수 있습니다. 객체를 추적하거나 지연 시간이 짧은 경우에 이 모드를 사용합니다. 예를 들어 동영상 스트림을 실제로 처리할 때 있습니다.

    단일 이미지 모드에서는 객체 인식기가 결과를 반환합니다. 디코더에 전달될 수 있습니다. 또한 경계 상자 다음에 결과를 반환하며 모두 사용 가능합니다. 그 결과 더 길 수 있습니다 또한 단일 이미지 모드에서는 ID가 할당되지 않았습니다. 지연 시간이 중요하지 않으며 부분적인 결과를 처리하는 것은 바람직하지 않습니다.

    여러 객체 감지 및 추적 false (기본값) | true

    최대 5개의 객체를 감지하고 추적할지, 아니면 가장 많은 객체만 감지하고 추적할지 여부 가시도 높은 객체 (기본값).

    객체 분류 false (기본값) | true

    감지된 객체를 대략적인 카테고리로 분류할지 여부입니다. 사용 설정하면 객체 인식기가 객체를 카테고리에는 패션 상품, 식품, 가정용품 장소, 식물.

    객체 감지 및 추적 API는 이 두 가지 핵심 용도에 최적화되어 있습니다. 사례:

    • 카메라에서 가장 눈에 띄는 물체를 실시간으로 감지하고 추적합니다. 뷰파인더를 사용할 수 있습니다.
    • 정적 이미지의 여러 객체를 감지합니다.

    이러한 사용 사례에 맞게 API를 구성하려면 다음 안내를 따르세요.

Swift

// Live detection and tracking
let options = ObjectDetectorOptions()
options.shouldEnableClassification = true

// Multiple object detection in static images
let options = ObjectDetectorOptions()
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true

Objective-C

// Live detection and tracking
MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init];
options.shouldEnableClassification = YES;

// Multiple object detection in static images
MLKObjectDetectorOptions *options = [[MLKOptions alloc] init];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
  1. ObjectDetector의 인스턴스를 가져옵니다.

Swift

let objectDetector = ObjectDetector.objectDetector()

// Or, to change the default settings:
let objectDetector = ObjectDetector.objectDetector(options: options)

Objective-C

MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector];

// Or, to change the default settings:
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];

2. 입력 이미지 준비

객체를 감지하고 추적하려면 각 이미지 또는 동영상 프레임에 대해 다음을 수행합니다. 스트림 모드를 사용 설정한 경우 VisionImage 객체를 CMSampleBuffer

VisionImage 객체를 UIImage 또는 CMSampleBuffer입니다.

UIImage를 사용하는 경우 다음 단계를 따르세요.

  • UIImage로 VisionImage 객체를 만듭니다. 올바른 .orientation를 지정해야 합니다.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

CMSampleBuffer를 사용하는 경우 다음 단계를 따르세요.

  • CMSampleBuffer

    이미지 방향을 가져오는 방법은 다음과 같습니다.

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • 다음을 사용하여 VisionImage 객체를 만듭니다. CMSampleBuffer 객체 및 방향:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. 이미지 처리

객체 감지기의 이미지 처리 중 하나에 VisionImage를 전달합니다. 메서드를 참조하세요. 비동기 process(image:) 메서드 또는 동기 results() 메서드

객체를 비동기식으로 감지하는 방법은 다음과 같습니다.

Swift

objectDetector.process(image) { objects, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !objects.isEmpty else {
    // No objects detected.
    return
  }

  // Success. Get object info here.
  // ...
}

Objective-C

[objectDetector processImage:image
                  completion:^(NSArray * _Nullable objects,
                               NSError * _Nullable error) {
                    if (error == nil) {
                      return;
                    }
                    if (objects.count == 0) {
                      // No objects detected.
                      return;
                    }

                    // Success. Get object info here.
                  }];

객체를 동기식으로 감지하려면 다음 안내를 따르세요.

Swift

var objects: [Object]
do {
  objects = try objectDetector.results(in: image)
} catch let error {
  print("Failed to detect object with error: \(error.localizedDescription).")
  return
}
guard !objects.isEmpty else {
  print("Object detector returned no results.")
  return
}

// Success. Get object info here.

Objective-C

NSError *error;
NSArray *objects = [objectDetector resultsInImage:image error:&error];
if (error == nil) {
  return;
}
if (objects.count == 0) {
  // No objects detected.
  return;
}

// Success. Get object info here.

4. 감지된 객체에 대한 정보 가져오기

이미지 프로세서 호출이 성공하면 이미지 프로세서는 Object를 완료 핸들러에 추가하거나 호출했는지 여부에 따라 달라집니다.

각 Object에는 다음 속성이 포함됩니다.

frame 객체의 위치를 나타내는 CGRect: 이미지
trackingID 여러 이미지에서 객체를 식별하는 정수 또는 다음에서 `nil` 입니다. 단일 이미지 모드입니다.
labels 인식기가 반환한 객체를 설명하는 라벨의 배열. 검사 프로그램 옵션이 있는 경우 속성이 비어 있습니다. shouldEnableClassification가 false로 설정되어 있습니다.

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID

  // If classification was enabled:
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence)"
    }.joined(separator:"\n")

}

Objective-C

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu",
      label.text, label.confidence, (unsigned long)label.index];
    ...
  }
}

사용성 및 성능 개선

최상의 사용자 환경을 위해 앱에서 다음 가이드라인을 따르세요.

  • 객체 감지 성공 여부는 객체의 시각적 복잡성에 따라 달라집니다. 포함 감지하기 위해서는 시각적 특징이 적은 물체는 이미지의 더 큰 부분을 차지합니다. 사용자에게 감지하려는 객체 종류에서 잘 작동하는 입력을 캡처하는 것입니다.
  • 분류를 사용할 때 떨어지지 않는 물체를 감지하려는 경우 지원되는 카테고리로 깔끔하게 분류하고 알려지지 않은 특수 처리를 구현하세요. 객체입니다.

머티리얼 디자인도 확인해 보세요. 머신러닝 기반의 특성 수집 패턴

실시간 애플리케이션에서 스트리밍 모드를 사용할 때 다음 가이드라인을 따르세요. 최상의 프레임 속도를 달성해야 합니다.

  • 대부분의 기기가 작동하지 않으므로 스트리밍 모드에서 다중 객체 감지를 사용하지 않습니다. 적절한 프레임 속도를 생성할 수 있어야 합니다.
  • 분류가 필요하지 않으면 사용 중지합니다.
  • 동영상 프레임을 처리하려면 감지기의 results(in:) 동기 API를 사용하세요. 전화걸기 AVCaptureVideoDataOutputSampleBufferDelegate님의 <ph type="x-smartling-placeholder"></ph> captureOutput(_, didOutput:from:) 함수를 사용하여 특정 동영상에서 동기식으로 결과를 가져옵니다. 있습니다. 유지 AVCaptureVideoDataOutput님의 alwaysDiscardsLateVideoFrames를 true로 설정하여 감지기 호출을 제한합니다. 새 동영상 프레임은 감지기가 실행되는 동안 사용할 수 있게 되면 삭제됩니다.
  • 감지기 출력을 사용하여 그래픽 이미지를 먼저 ML Kit에서 결과를 가져온 후 이미지를 하나의 단계로 오버레이할 수 있습니다. 이렇게 하면 처리되어야 합니다 자세한 내용은 updatePreviewOverlayViewWithLastFrame을 를 참조하세요.