ML Kit предоставляет оптимизированный SDK для сегментации селфи. Ресурсы Selfie Segmenter статически связаны с вашим приложением во время сборки. Это увеличит размер вашего приложения до 24 МБ, а задержка API может варьироваться от ~ 7 мс до ~ 12 мс в зависимости от размера входного изображения, измеренного на iPhone X.
Попробуйте это
- Поэкспериментируйте с примером приложения , чтобы увидеть пример использования этого API.
Прежде чем вы начнете
Включите в свой подфайл следующие библиотеки ML Kit:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
После установки или обновления модулей вашего проекта откройте проект Xcode, используя его файл .
xcworkspace
. ML Kit поддерживается в Xcode версии 13.2.1 или выше.
1. Создайте экземпляр сегментатора.
Чтобы выполнить сегментацию селфи-изображения, сначала создайте экземпляр Segmenter
с помощью SelfieSegmenterOptions
и при необходимости укажите параметры сегментации.
Опции сегментатора
Режим сегментатора
Segmenter
работает в двух режимах. Убедитесь, что вы выбрали тот, который соответствует вашему варианту использования.
STREAM_MODE (default)
Этот режим предназначен для потоковой передачи кадров с видео или камеры. В этом режиме сегментатор будет использовать результаты предыдущих кадров для получения более плавных результатов сегментации.
SINGLE_IMAGE_MODE (default)
Этот режим предназначен для отдельных изображений, не связанных друг с другом. В этом режиме сегментатор будет обрабатывать каждое изображение независимо, без сглаживания кадров.
Включить маску необработанного размера
Просит сегментатор вернуть необработанную маску размера, соответствующую выходному размеру модели.
Размер необработанной маски (например, 256x256) обычно меньше размера входного изображения.
Без указания этой опции сегментатор изменит масштаб необработанной маски в соответствии с размером входного изображения. Рассмотрите возможность использования этой опции, если вы хотите применить настраиваемую логику масштабирования или масштабирование не требуется для вашего варианта использования.
Укажите параметры сегментатора:
Быстрый
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Цель-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Наконец, получите экземпляр Segmenter
. Передайте указанные вами параметры:
Быстрый
let segmenter = Segmenter.segmenter(options: options)
Цель-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Подготовьте входное изображение
Чтобы сегментировать селфи, выполните следующие действия для каждого изображения или кадра видео. Если вы включили потоковый режим, вам необходимо создать объекты VisionImage
из CMSampleBuffer
s.
Создайте объект VisionImage
используя UIImage
или CMSampleBuffer
.
Если вы используете UIImage
, выполните следующие действия:
- Создайте объект
VisionImage
с помощьюUIImage
. Обязательно укажите правильную.orientation
.Быстрый
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Цель-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Если вы используете
CMSampleBuffer
, выполните следующие действия:Укажите ориентацию данных изображения, содержащихся в
CMSampleBuffer
.Чтобы получить ориентацию изображения:
Быстрый
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 } }
Цель-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
и ориентацию:Быстрый
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Цель-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Обработка изображения
Передайте объект
VisionImage
одному из методов обработки изображенийSegmenter
. Вы можете использовать либо метод асинхронногоprocess(image:)
, либо метод синхронныхresults(in:)
.Чтобы синхронно выполнить сегментацию селфи-изображения:
Быстрый
var mask: [SegmentationMask] do { mask = try segmenter.results(in: image) } catch let error { print("Failed to perform segmentation with error: \(error.localizedDescription).") return } // Success. Get a segmentation mask here.
Цель-C
NSError *error; MLKSegmentationMask *mask = [segmenter resultsInImage:image error:&error]; if (error != nil) { // Error. return; } // Success. Get a segmentation mask here.
Чтобы выполнить сегментацию селфи-изображения асинхронно:
Быстрый
segmenter.process(image) { mask, error in guard error == nil else { // Error. return } // Success. Get a segmentation mask here.
Цель-C
[segmenter processImage:image completion:^(MLKSegmentationMask * _Nullable mask, NSError * _Nullable error) { if (error != nil) { // Error. return; } // Success. Get a segmentation mask here. }];
4. Получите маску сегментации
Получить результат сегментации можно следующим образом:
Быстрый
let maskWidth = CVPixelBufferGetWidth(mask.buffer) let maskHeight = CVPixelBufferGetHeight(mask.buffer) CVPixelBufferLockBaseAddress(mask.buffer, CVPixelBufferLockFlags.readOnly) let maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer) var maskAddress = CVPixelBufferGetBaseAddress(mask.buffer)!.bindMemory( to: Float32.self, capacity: maskBytesPerRow * maskHeight) for _ in 0...(maskHeight - 1) { for col in 0...(maskWidth - 1) { // Gets the confidence of the pixel in the mask being in the foreground. let foregroundConfidence: Float32 = maskAddress[col] } maskAddress += maskBytesPerRow / MemoryLayout<Float32>.size }
Цель-C
size_t width = CVPixelBufferGetWidth(mask.buffer); size_t height = CVPixelBufferGetHeight(mask.buffer); CVPixelBufferLockBaseAddress(mask.buffer, kCVPixelBufferLock_ReadOnly); size_t maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer); float *maskAddress = (float *)CVPixelBufferGetBaseAddress(mask.buffer); for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { // Gets the confidence of the pixel in the mask being in the foreground. float foregroundConfidence = maskAddress[col]; } maskAddress += maskBytesPerRow / sizeof(float); }
Полный пример использования результатов сегментации см. в образце быстрого запуска ML Kit .
Советы по повышению производительности
Качество результатов зависит от качества входного изображения:
- Чтобы ML Kit мог получить точный результат сегментации, изображение должно быть не менее 256x256 пикселей.
- Если вы выполняете сегментацию селфи в приложении реального времени, вам также может потребоваться учитывать общие размеры входных изображений. Изображения меньшего размера можно обрабатывать быстрее, поэтому, чтобы уменьшить задержку, снимайте изображения с более низким разрешением, но помните о вышеуказанных требованиях к разрешению и следите за тем, чтобы объект занимал как можно большую часть изображения.
- Плохая фокусировка изображения также может повлиять на точность. Если вы не получили приемлемых результатов, попросите пользователя повторно сделать снимок.
Если вы хотите использовать сегментацию в приложении реального времени, следуйте этим рекомендациям для достижения наилучшей частоты кадров:
- Используйте режим сегментации
stream
. - Рассмотрите возможность захвата изображений с более низким разрешением. Однако также имейте в виду требования к размеру изображения этого API.
- Для обработки видеокадров используйте синхронный API
results(in:)
сегментатора. Вызовите этот метод из функции captureOutput(_, DidOutput:from:) AVCaptureVideoDataOutputSampleBufferDelegate , чтобы синхронно получить результаты из данного видеокадра. Оставьте для AVCaptureVideoDataOutput значение AlwaysDiscardsLateVideoFrames как true, чтобы ограничить вызовы сегментатора. Если новый видеокадр становится доступным во время работы сегментатора, он будет удален. - Если вы используете выходные данные сегментатора для наложения графики на входное изображение, сначала получите результат из ML Kit, затем визуализируйте изображение и наложите его за один шаг. При этом вы выполняете рендеринг на поверхность дисплея только один раз для каждого обработанного входного кадра. Пример см. в классах PreviewOverlayView и CameraViewController в образце быстрого запуска ML Kit .
Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2024-08-13 UTC.
[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Отсутствует нужная мне информация" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Слишком сложен/слишком много шагов" },{ "type": "thumb-down", "id": "outOfDate", "label":"Устарел" },{ "type": "thumb-down", "id": "translationIssue", "label":"Проблема с переводом текста" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Проблемы образцов/кода" },{ "type": "thumb-down", "id": "otherDown", "label":"Другое" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Прост для понимания" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Помог мне решить мою проблему" },{ "type": "thumb-up", "id": "otherUp", "label":"Другое" }] { "last_modified": "Последнее обновление: 2024-08-13 UTC.", "state": "" }