Udhëzues për ndarjen e imazheve për iOS

Detyra "Imazh Segmenter" ju lejon të ndani imazhet në rajone bazuar në kategoritë e paracaktuara dhe të aplikoni efekte vizuale si turbullimi i sfondit. Këto udhëzime ju tregojnë se si të përdorni Segmenterin e Imazheve me aplikacionet iOS.

Shembulli i kodit i përshkruar në këto udhëzime është i disponueshëm në GitHub .

Ju mund ta shihni këtë detyrë në veprim duke parë demonstrimin në ueb . Për më shumë informacion rreth aftësive, modeleve dhe opsioneve të konfigurimit të kësaj detyre, shihni Përmbledhjen .

Shembull kodi

Shembulli i kodit MediaPipe Tasks përmban një zbatim të thjeshtë të një aplikacioni Image Segmenter për iOS.

Shembulli zbaton një segmentues imazhi që nxjerr maskat e kategorive. Ai përdor kamerën në një pajisje fizike iOS për të kryer segmentimin e imazheve në një furnizim të drejtpërdrejtë të kamerës ose në imazhe dhe video nga galeria e pajisjes.

Mund ta përdorni aplikacionin si pikënisje për aplikacionin tuaj iOS ose t'i referoheni kur modifikoni një aplikacion ekzistues. Shembulli i kodit të Segmenterit të Imazhit është pritur në GitHub .

Shkarkoni kodin

Udhëzimet e mëposhtme ju tregojnë se si të krijoni një kopje lokale të kodit shembull duke përdorur mjetin e linjës së komandës git .

Për të shkarkuar kodin shembull:

  1. Klononi depon e git duke përdorur komandën e mëposhtme:

    git clone https://github.com/google-ai-edge/mediapipe-samples/
    
  2. Opsionale, konfiguroni shembullin tuaj të git për të përdorur arkëtimin e rrallë, në mënyrë që të keni vetëm skedarët për shembullin e aplikacionit Image Segmenter:

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

Pas krijimit të një versioni lokal të kodit shembull, mund të instaloni bibliotekën e detyrave MediaPipe, të hapni projektin duke përdorur Xcode dhe të ekzekutoni aplikacionin. Për udhëzime, shihni Udhëzuesin e konfigurimit për iOS .

Komponentët kryesorë

Skedarët e mëposhtëm përmbajnë kodin vendimtar për shembullin e aplikacionit të Segmenterit të imazhit:

  • ImageSegmenterService.swift : Inicializon Segmenterin e Imazhit, trajton zgjedhjen e modelit dhe ekzekuton konkluzionet në të dhënat hyrëse.
  • CameraViewController.swift : Zbaton ndërfaqen e përdoruesit për modalitetin e hyrjes së furnizimit të drejtpërdrejtë të kamerës dhe vizualizon rezultatet.
  • MediaLibraryViewController.swift Zbaton ndërfaqen e përdoruesit për modalitetin e futjes së imazheve dhe skedarëve video dhe vizualizon rezultatet.

Konfigurimi

Ky seksion përshkruan hapat kryesorë për konfigurimin e mjedisit tuaj të zhvillimit dhe projekteve të kodit për të përdorur Segmenterin e imazhit. Për informacion të përgjithshëm mbi konfigurimin e mjedisit tuaj të zhvillimit për përdorimin e detyrave të MediaPipe, duke përfshirë kërkesat e versionit të platformës, shihni udhëzuesin e konfigurimit për iOS .

varësitë

Image Segmenter përdor bibliotekën MediaPipeTasksVision , e cila duhet të instalohet duke përdorur CocoaPods. Biblioteka është e pajtueshme me të dy aplikacionet Swift dhe Objective-C dhe nuk kërkon ndonjë konfigurim shtesë specifik për gjuhën.

Për udhëzime për instalimin e CocoaPods në macOS, referojuni udhëzuesit të instalimit të CocoaPods . Për udhëzime se si të krijoni një Podfile me pods-et e nevojshme për aplikacionin tuaj, referojuni Përdorimit të CocoaPods .

Shtoni podin MediaPipeTasksVision në Podfile duke përdorur kodin e mëposhtëm:

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

Nëse aplikacioni juaj përfshin objektiva testimi të njësisë, referojuni Udhëzuesit të konfigurimit për iOS për informacion shtesë mbi konfigurimin e skedarit tuaj Podfile .

Model

Detyra MediaPipe Image Segmenter kërkon një model të trajnuar që është në përputhje me këtë detyrë. Për më shumë informacion rreth modeleve të trajnuara të disponueshme për Segmenterin e imazheve, shihni seksionin Modelet e përmbledhjes së detyrave.

Zgjidhni dhe shkarkoni një model dhe shtoni atë në drejtorinë e projektit tuaj duke përdorur Xcode. Për udhëzime se si të shtoni skedarë në projektin tuaj Xcode, referojuni Menaxhimi i skedarëve dhe dosjeve në projektin tuaj Xcode .

Përdorni veçorinë BaseOptions.modelAssetPath për të specifikuar shtegun drejt modelit në paketën tuaj të aplikacionit. Për një shembull kodi, shihni seksionin tjetër.

Krijo detyrën

Ju mund të krijoni detyrën "Imazh Segmenter" duke thirrur një nga inicializuesit e tij. Inicializuesi ImageSegmenter(options:) pranon vlerat për opsionet e konfigurimit.

Nëse nuk keni nevojë për një Segmenter imazhi të inicializuar me opsione të personalizuara të konfigurimit, mund të përdorni iniciatorin ImageSegmenter(modelPath:) për të krijuar një Segmenter imazhi me opsionet e paracaktuara. Për më shumë informacion rreth opsioneve të konfigurimit, shihni Përmbledhjen e konfigurimit .

Detyra "Segmentuesi i imazhit" mbështet 3 lloje të dhënash hyrëse: imazhe statike, skedarë video dhe transmetime video të drejtpërdrejta. Si parazgjedhje, ImageSegmenter(modelPath:) inicializon një detyrë për imazhet statike. Nëse dëshironi që detyra juaj të inicializohet për të përpunuar skedarë video ose transmetime video të drejtpërdrejta, përdorni ImageSegmenter(options:) për të specifikuar modalitetin e ekzekutimit të videos ose transmetimit të drejtpërdrejtë. Modaliteti i transmetimit të drejtpërdrejtë kërkon gjithashtu opsionin shtesë të konfigurimit të imageSegmenterLiveStreamDelegate , i cili i mundëson Segmenterit të imazhit t'i japë delegatit rezultatet e segmentimit të imazheve në mënyrë asinkrone.

Zgjidhni skedën që korrespondon me modalitetin tuaj të ekzekutimit për të parë se si të krijoni detyrën dhe të ekzekutoni konkluzionet.

Swift

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    
import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    
import MediaPipeTasksVision

// Class that conforms to the `imageSegmenterLiveStreamDelegate` protocol and
// implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.
class ImageSegmenterResultProcessor: NSObject, ImageSegmenterLiveStreamDelegate {

  func imageSegmenter(
    _ imageSegmenter: ImageSegmenter,
    didFinishSegmentation result: ImageSegmenterResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image segmentation result or errors here.

  }
}

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `ImageSegmenterLiveStreamDelegate` protocol.
let processor = ImageSegmenterResultProcessor()
options.imageSegmenterLiveStreamDelegate = processor

let imageSegmenter = try ImageSegmenter(options: options)
    

Objektivi-C

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    
@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    
@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageSegmenterLiveStreamDelegate` protocol
// and implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.

@interface APPImageSegmenterResultProcessor : NSObject 

@end

@implementation APPImageSegmenterResultProcessor

-   (void)imageSegmenter:(MPPImageSegmenter *)imageSegmenter
    didFinishSegmentationWithResult:(MPPImageSegmenterResult *)imageSegmenterResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the image segmentation result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `MPPImageSegmenterLiveStreamDelegate` protocol.
APPImageSegmenterResultProcessor *processor =
  [APPImageSegmenterResultProcessor new];
options.imageSegmenterLiveStreamDelegate = processor;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

Implementimi i kodit të shembullit të Segmenterit të imazhit lejon përdoruesin të kalojë midis mënyrave të përpunimit. Qasja e bën kodin e krijimit të detyrës më të komplikuar dhe mund të mos jetë i përshtatshëm për rastin tuaj të përdorimit.

Opsionet e konfigurimit

Kjo detyrë ka opsionet e mëposhtme të konfigurimit për aplikacionet iOS:

Emri i opsionit Përshkrimi Gama e vlerave Vlera e paracaktuar
runningMode Vendos modalitetin e ekzekutimit për detyrën. Ekzistojnë tre mënyra:

IMAGE: Modaliteti për hyrjet e një imazhi të vetëm.

VIDEO: Modaliteti për kornizat e dekoduara të një videoje.

LIVE_STREAM: Modaliteti për një transmetim të drejtpërdrejtë të të dhënave hyrëse, si p.sh. nga një aparat fotografik. Në këtë modalitet, ImageSegmenterLiveStreamDelegate duhet të vendoset në një shembull të një klase që zbaton ImageSegmenterLiveStreamDelegate për të marrë rezultatet e segmentimit në mënyrë asinkrone.
{ RunningMode.image, RunningMode.video, RunningMode.liveStream } RunningMode.image
shouldOutputCategoryMask Nëse vendoset në True , dalja përfshin një maskë segmentimi si një imazh uint8, ku çdo vlerë piksel tregon vlerën e kategorisë fituese. { True, False } False
shouldOutputConfidenceMasks Nëse vendoset në True , dalja përfshin një maskë segmentimi si një imazh me vlerë notuese, ku çdo vlerë notuese përfaqëson hartën e rezultateve të besimit të kategorisë. { True, False } True
displayNamesLocale Vendos gjuhën e etiketave për t'u përdorur për emrat e shfaqur të dhëna në meta të dhënat e modelit të detyrës, nëse disponohet. Parazgjedhja është en për anglisht. Ju mund të shtoni etiketa të lokalizuara në meta të dhënat e një modeli të personalizuar duke përdorur API-në e shkrimtarit metadata TensorFlow Lite Kodi lokal sq
result_callback Vendos dëgjuesin e rezultateve që të marrë rezultatet e segmentimit në mënyrë asinkrone kur segmentuesi i imazhit është në modalitetin LIVE_STREAM . Mund të përdoret vetëm kur modaliteti i ekzekutimit është caktuar në LIVE_STREAM N/A N/A

Kur modaliteti i ekzekutimit caktohet në LIVE_STREAM , Segmentuesi i imazhit kërkon opsionin shtesë të konfigurimit të imageSegmenterLiveStreamDelegate , i cili i mundëson Segmenterit të imazhit të japë rezultatet e segmentimit të imazhit në mënyrë asinkrone. I deleguari duhet të zbatojë metodën imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) , të cilën Segmentuesi i imazhit e thërret pas përpunimit të rezultateve të kryerjes së segmentimit në çdo kornizë.

Emri i opsionit Përshkrimi Gama e vlerave Vlera e paracaktuar
imageSegmenterLiveStreamDelegate Aktivizon Segmenterin e Imazhit të marrë rezultatet e kryerjes së segmentimit të imazhit në mënyrë asinkrone në modalitetin e transmetimit të drejtpërdrejtë. Klasa, instanca e së cilës është caktuar në këtë veti, duhet të zbatojë metodën imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) . E pazbatueshme Nuk është vendosur

Përgatitni të dhënat

Ju duhet të konvertoni imazhin ose kornizën hyrëse në një objekt MPImage përpara se ta kaloni atë te Segmentuesi i Imazhit. MPImage mbështet lloje të ndryshme të formateve të imazhit iOS dhe mund t'i përdorë ato në çdo modalitet ekzekutimi për përfundime. Për më shumë informacion rreth MPImage , referojuni MPImage API .

Zgjidhni një format imazhi iOS bazuar në rastin tuaj të përdorimit dhe mënyrën e ekzekutimit që kërkon aplikacioni juaj. MPImage pranon formatet e imazhit UIImage , CVPixelBuffer dhe CMSampleBuffer iOS.

UIIimazh

Formati UIImage është i përshtatshëm për mënyrat e mëposhtme të funksionimit:

  • Imazhet: imazhet nga një grup aplikacioni, galeri përdoruesish ose sistem skedarësh të formatuar si imazhe UIImage mund të konvertohen në një objekt MPImage .

  • Videot: përdorni AVAssetImageGenerator për të nxjerrë kornizat e videos në formatin CGImage , më pas i konvertoni ato në imazhe UIImage .

// 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)
    
// 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];
    

Shembulli inicializon një MPImage me orientimin e paracaktuar UIImage.Orientation.Up . Mund të inicializoni një MPImage me ndonjë nga vlerat e mbështetura të UIImage.Orientation . Segmentuesi i imazhit nuk mbështet orientime të pasqyruara si .upMirrored , .downMirrored , .leftMirrored , .rightMirrored .

Për më shumë informacion rreth UIImage , referojuni Dokumentacionit të Zhvilluesit të UIImage Apple .

CVPixelBuffer

Formati CVPixelBuffer është i përshtatshëm për aplikacionet që gjenerojnë korniza dhe përdorin kornizën iOS CoreImage për përpunim.

Formati CVPixelBuffer është i përshtatshëm për mënyrat e mëposhtme të funksionimit:

  • Imazhet: aplikacionet që gjenerojnë imazhe CVPixelBuffer pas disa përpunimit duke përdorur kornizën CoreImage të iOS mund të dërgohen te Segmentuesi i imazhit në modalitetin e ekzekutimit të imazhit.

  • Videot: kornizat e videove mund të konvertohen në formatin CVPixelBuffer për përpunim dhe më pas të dërgohen në Segmenterin e Imazheve në modalitetin e videos.

  • transmetim i drejtpërdrejtë: aplikacionet që përdorin një kamerë iOS për të gjeneruar korniza mund të konvertohen në formatin CVPixelBuffer për përpunim përpara se të dërgohen në Segmenterin e imazhit në modalitetin e transmetimit të drejtpërdrejtë.

// 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)
    
// 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];
    

Për më shumë informacion rreth CVPixelBuffer , referojuni Dokumentacionit të Zhvilluesit të Apple CVPixelBuffer .

CMSampleBuffer

Formati CMSampleBuffer ruan mostrat e mediave të një lloji uniform të medias dhe është i përshtatshëm për modalitetin e ekzekutimit të transmetimit të drejtpërdrejtë. Kornizat e drejtpërdrejta nga kamerat iOS shpërndahen në mënyrë asinkrone në formatin CMSampleBuffer nga iOS AVCaptureVideoDataOutput .

// 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)
    
// 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];
    

Për më shumë informacion rreth CMSampleBuffer , referojuni Dokumentacionit të Zhvilluesit të Apple CMSampleBuffer .

Drejtoni detyrën

Për të ekzekutuar Segmenterin e Imazhit, përdorni metodën segment() specifike për modalitetin e caktuar të ekzekutimit:

  • Imazhi i palëvizshëm: segment(image:)
  • Video: segment(videoFrame:timestampInMilliseconds:)
  • Transmetimi i drejtpërdrejtë: segmentAsync(image:timestampInMilliseconds:)

Shembujt e mëposhtëm të kodit tregojnë shembuj të thjeshtë se si të ekzekutoni Segmenterin e imazhit në këto mënyra të ndryshme ekzekutimi:

Swift

let result = try imageSegmenter.segment(image: image)
    
let result = try imageSegmenter.segment(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    
try imageSegmenter.segmentAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objektivi-C

MPPImageSegmenterResult *result =
  [imageSegmenter segmentImage:image error:nil];
    
MPPImageSegmenterResult *result =
  [imageSegmenter segmentVideoFrame:image
            timestampInMilliseconds:timestamp
                              error:nil];
    
BOOL success =
  [imageSegmenter segmentAsyncImage:image
            timestampInMilliseconds:timestamp
                              error:nil];
    

Shembulli i kodit të Segmenterit të imazhit tregon implementimet e secilit prej këtyre mënyrave në më shumë detaje segment(image:) , segment(videoFrame:timestampInMilliseconds:) dhe segmentAsync(image:timestampInMilliseconds:) .

Vini re sa vijon:

  • Kur ekzekutoni në modalitetin e videos ose në modalitetin e transmetimit të drejtpërdrejtë, duhet të jepni gjithashtu vulën kohore të kornizës së hyrjes në detyrën "Segmentuesi i imazhit".

  • Kur funksionon në modalitetin e imazhit ose të videos, detyra "Segmentuesi i imazhit" bllokon fillin aktual derisa të përfundojë përpunimin e imazhit ose kornizës hyrëse. Për të shmangur bllokimin e fillit aktual, ekzekutoni përpunimin në një fill në sfond duke përdorur kornizat iOS Dispatch ose NSOoperation .

  • Kur ekzekutohet në modalitetin e transmetimit të drejtpërdrejtë, detyra e Segmenterit të imazhit kthehet menjëherë dhe nuk e bllokon lidhjen aktuale. Ai thërret metodën imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) me segmentuesin e imazhit pas përpunimit të çdo kornize hyrëse. Segmentuesi i imazhit e thërret këtë metodë në mënyrë asinkrone në një radhë të dedikuar dërgimi serik. Për shfaqjen e rezultateve në ndërfaqen e përdoruesit, dërgoni rezultatet në radhën kryesore pas përpunimit të rezultateve. Nëse funksioni segmentAsync thirret kur detyra e Segmenterit të imazhit është e zënë me përpunimin e një kuadri tjetër, Segmentuesi i imazhit injoron kornizën e re hyrëse.

Trajtoni dhe shfaqni rezultatet

Pas ekzekutimit të konkluzionit, detyra e Segmenterit të imazhit kthen një objekt ImageSegmenterResult i cili përmban rezultatet e detyrës së segmentimit. Përmbajtja e daljes varet nga lloji i daljes që keni vendosur kur keni konfiguruar detyrën.

Imazhet e mëposhtme tregojnë një vizualizim të daljes së detyrës për një maskë me vlerë kategorie. Gama e maskës së kategorisë është [0, 255] dhe çdo vlerë piksel përfaqëson indeksin e kategorisë fituese të prodhimit të modelit. Indeksi i kategorisë fituese ka rezultatin më të lartë midis kategorive që modeli mund të njohë.

Dy vajza hipur në kalë dhe një vajzë që ecën pranë kalitMaska e imazhit që përshkruan formën e vajzave dhe kalit nga imazhi i mëparshëm. Forma e të tre vajzave dhe kalit janë maskuar me saktësi

Dalja origjinale e imazhit dhe maskës së kategorisë. Imazhi burim nga grupi i të dhënave Pascal VOC 2012 .

Shembulli i kodit të Segmenterit të Imazhit tregon se si të shfaqen rezultatet e Segmenterit të Imazhit, shikoni shembullin e kodit për detaje.