Giriş
Merhaba Dünya! eğiticisi, iOS'i geliştirmek için MediaPipe Framework'ü kullanır iOS'te MediaPipe grafiği çalıştıran bir uygulamadır.
Ne oluşturacaksınız?
Canlı bir videoya gerçek zamanlı Sobel kenar algılaması için uygulanan basit bir kamera uygulaması akışla aktarmanızı sağlar.

Kurulum
- Sisteminize MediaPipe Framework'ü yükleme için Çerçeve yüklemesi kurulumuna bakın rehberini inceleyin.
- Geliştirme için iOS cihazınızı ayarlayın.
- iOS uygulamasını oluşturmak ve dağıtmak için sisteminizde Bazel'i kurun.
Kenar algılama grafiği
Şu grafiği kullanacağız: edge_detection_mobile_gpu.pbtxt:
# MediaPipe graph that performs GPU Sobel edge detection on a live video stream.
# Used in the examples
# mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic:helloworld
# and mediapipe/examples/ios/helloworld.
# Images coming into and out of the graph.
input_stream: "input_video"
output_stream: "output_video"
# Converts RGB images into luminance images, still stored in RGB format.
node: {
calculator: "LuminanceCalculator"
input_stream: "input_video"
output_stream: "luma_video"
}
# Applies the Sobel filter to luminance images stored in RGB format.
node: {
calculator: "SobelEdgesCalculator"
input_stream: "luma_video"
output_stream: "output_video"
}
Grafik görselleştirmesi aşağıda gösterilmektedir:

Bu grafikte, tüm gelen kareler için input_video adlı tek bir giriş akışı bulunuyor
bir veri feed'i seçin.
Grafikteki ilk düğüm olan LuminanceCalculator, tek bir paket alır (görüntü
çerçeve) ve bir OpenGL gölgelendirici kullanarak parlaklık değişikliği uygular. Bunun sonucunda
resim çerçevesi, luma_video çıkış akışına gönderilir.
İkinci düğüm olan SobelEdgesCalculator, gelen içeriğe uç algılamayı uygular
luma_video akışındaki paketler ve çıkışlar, output_video çıkışıyla sonuçlanır
akış şeklinde gösterilir.
iOS uygulamamız, output_video çıktısının resim çerçevelerini görüntüler
akış şeklinde gösterilir.
İlk minimum uygulama kurulumu
Öncelikle basit bir iOS uygulamasıyla başlayıp bazel ürününün nasıl kullanılacağını göstereceğiz.
sahip olacaksınız.
İlk olarak Dosya > üzerinden bir XCode projesi oluşturun Yeni > Tek Görünüm Uygulaması.
Ürün adını "HelloWorld" olarak ayarlayın ve uygun bir kuruluş kullanın
com.google.mediapipe gibi bir tanımlayıcı içerir. Kuruluş tanımlayıcısı
ile birlikte ürün adı, uygulama için bundle_id olacaktır. Örneğin,
com.google.mediapipe.HelloWorld.
Dili Objective-C olarak ayarlayın.
Projeyi uygun bir konuma kaydedin. Buna şöyle diyelim:
$PROJECT_TEMPLATE_LOC Bu nedenle projeniz,
$PROJECT_TEMPLATE_LOC/HelloWorld dizini. Bu dizinde şunlar yer alır:
HelloWorld adlı başka bir dizin ve bir HelloWorld.xcodeproj dosyası.
HelloWorld.xcodeproj, daha önce belirttiğimiz gibi bu eğitimde yararlı olmayacak
bazel kullanarak iOS uygulamasını oluşturabilirsiniz. The content of the
$PROJECT_TEMPLATE_LOC/HelloWorld/HelloWorld dizini aşağıda listelenmiştir:
AppDelegate.hveAppDelegate.mViewController.hveViewController.mmain.mInfo.plistMain.storyboardveLaunch.storyboardAssets.xcassetsdizini.
Bu dosyaları HelloWorld adlı dizine kopyalayıp erişimi olan bir konuma kopyalayın
MediaPipe Framework kaynak kodu kullanılır. Örneğin,
bu eğitimde oluşturacağımız uygulama şuradadır:
mediapipe/examples/ios/HelloWorld Bu yolu
Codelab boyunca $APPLICATION_PATH.
$APPLICATION_PATH içinde bir BUILD dosyası oluşturun ve aşağıdaki derlemeyi ekleyin
kurallarınız:
MIN_IOS_VERSION = "11.0"
load(
"@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
)
ios_application(
name = "HelloWorldApp",
bundle_id = "com.google.mediapipe.HelloWorld",
families = [
"iphone",
"ipad",
],
infoplists = ["Info.plist"],
minimum_os_version = MIN_IOS_VERSION,
provisioning_profile = "//mediapipe/examples/ios:developer_provisioning_profile",
deps = [":HelloWorldAppLibrary"],
)
objc_library(
name = "HelloWorldAppLibrary",
srcs = [
"AppDelegate.m",
"ViewController.m",
"main.m",
],
hdrs = [
"AppDelegate.h",
"ViewController.h",
],
data = [
"Base.lproj/LaunchScreen.storyboard",
"Base.lproj/Main.storyboard",
],
sdk_frameworks = [
"UIKit",
],
deps = [],
)
objc_library kuralı, AppDelegate ve
ViewController dersler, main.m ve uygulamanın resimli taslakları. İlgili içeriği oluşturmak için kullanılan
şablonlu uygulama yalnızca UIKit SDK'sına bağlıdır.
ios_application kuralı HelloWorldAppLibrary Objective-C kitaplığını kullanır
iOS cihazınıza yüklenmek üzere bir iOS uygulaması oluşturmak için oluşturulan bir web sitesini ziyaret edin.
Uygulamayı derlemek için bir terminalde aşağıdaki komutu kullanın:
bazel build -c opt --config=ios_arm64 <$APPLICATION_PATH>:HelloWorldApp'
Örneğin HelloWorldApp uygulamasını
mediapipe/examples/ios/helloworld için aşağıdaki komutu kullanın:
bazel build -c opt --config=ios_arm64 mediapipe/examples/ios/helloworld:HelloWorldApp
Ardından XCode'a geri dönün, Window'u açın > Cihazlar ve Simülatörler,
cihazınıza yükleyin ve yukarıdaki komutla oluşturulan .ipa dosyasını cihazınıza ekleyin.
iOS Framework uygulamalarını kurma ve derleme ile ilgili belgeyi aşağıda bulabilirsiniz.
Cihazınızda uygulamayı açın. Boş olduğu için boş beyaz ekran.
Canlı görüntüleme feed'i için kamerayı kullanma
Bu eğitimde, MPPCameraInputSource sınıfını kullanarak
çerçeveleri seçin. Bu sınıf, aşağıdaki işlemleri yapmak için AVCaptureSession API'sini kullanır:
otomatik olarak oluşturulur.
Ancak bu sınıfı kullanmadan önce Info.plist dosyasını kamerayı destekleyecek şekilde değiştirin
elde etti.
ViewController.m içine aşağıdaki içe aktarma satırını ekleyin:
#import "mediapipe/objc/MPPCameraInputSource.h"
Nesne oluşturmak için aşağıdaki kodu uygulama bloğuna ekleyin
_cameraSource:
@implementation ViewController {
// Handles camera access via AVCaptureSession library.
MPPCameraInputSource* _cameraSource;
}
Şu kodu viewDidLoad() alanına ekleyin:
-(void)viewDidLoad {
[super viewDidLoad];
_cameraSource = [[MPPCameraInputSource alloc] init];
_cameraSource.sessionPreset = AVCaptureSessionPresetHigh;
_cameraSource.cameraPosition = AVCaptureDevicePositionBack;
// The frame's native format is rotated with respect to the portrait orientation.
_cameraSource.orientation = AVCaptureVideoOrientationPortrait;
}
Kod _cameraSource işlemini başlatır, yakalama oturumu hazır ayarını ayarlar ve
bulun.
_cameraSource içinden kareleri uygulamamıza almamız gerekiyor
Bunları görüntülemek için ViewController. MPPCameraInputSource, şunun bir alt sınıfıdır:
Yetki verilmiş kullanıcıları için bir protokol sağlayan MPPInputSource
MPPInputSourceDelegate. Bu durumda ViewController uygulamamız, yetki verilmiş kullanıcı
/ _cameraSource.
ViewController arayüzünün tanımını uygun şekilde güncelleyin:
@interface ViewController () <MPPInputSourceDelegate>
Kamera kurulumunu yönetmek ve gelen kareleri işlemek için bir
ana sıradan farklıdır. Aşağıdakini
ViewController:
// Process camera frames on this queue.
dispatch_queue_t _videoQueue;
viewDidLoad() içinde, başlatıldıktan sonra aşağıdaki satırı ekleyin
_cameraSource nesne:
[_cameraSource setDelegate:self queue:_videoQueue];
Kurulumu ayarlamadan önce sırayı başlatmak için aşağıdaki kodu ekleyin
_cameraSource nesne:
dispatch_queue_attr_t qosAttribute = dispatch_queue_attr_make_with_qos_class(
DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, /*relative_priority=*/0);
_videoQueue = dispatch_queue_create(kVideoQueueLabel, qosAttribute);
Şunun için önceliği QOS_CLASS_USER_INTERACTIVE olan bir seri sırası kullanacağız:
fotoğraf makinesi çerçeveleri işleniyor.
Dosyanın üst kısmına başlık içe aktarıldıktan sonra, aşağıdaki satırı
arayüzü/uygulaması ViewController:
static const char* kVideoQueueLabel = "com.google.mediapipe.example.videoQueue";
MPPInputSourceDelegate protokolündeki herhangi bir yöntemi uygulamadan önce
önce kamera çerçevelerini görüntüleyecek bir yöntem ayarlayın. Mediapipe çerçevesi
MPPLayerRenderer adlı başka bir yardımcı programı kullanır. Bu
yardımcı programı CVPixelBufferRef nesnelerini görüntülemek için kullanılabilir.
MPPCameraInputSource tarafından yetki verilen kullanıcılara sağlanan resimler.
ViewController.m içine aşağıdaki içe aktarma satırını ekleyin:
#import "mediapipe/objc/MPPLayerRenderer.h"
Ekranın resimlerini görüntülemek için adlı yeni bir UIView nesnesi eklememiz gerekir.
ViewController - _liveView.
Aşağıdaki satırları ViewController uygulama bloğuna ekleyin:
// Display the camera preview frames.
IBOutlet UIView* _liveView;
// Render frames in a layer.
MPPLayerRenderer* _renderer;
Main.storyboard menüsüne gidin, nesne kitaplığındanUIView
ViewController sınıfından View. Bu görünümden şuna bir referans çıkışı ekleyin:
ViewController sınıfına eklediğiniz _liveView nesnesi. Yeniden boyutlandır
ortalanmış olacak ve uygulama ekranının tamamını kaplayacak şekilde
görünür.
ViewController.m sayfasına dönün ve aşağıdaki kodu viewDidLoad() içine ekleyin:
_renderer nesnesini başlatın:
_renderer = [[MPPLayerRenderer alloc] init];
_renderer.layer.frame = _liveView.layer.bounds;
[_liveView.layer addSublayer:_renderer.layer];
_renderer.frameScaleMode = MPPFrameScaleModeFillAndCrop;
Kameradan kare almak için aşağıdaki yöntemi uygulayacağız:
// Must be invoked on _videoQueue.
- (void)processVideoFrame:(CVPixelBufferRef)imageBuffer
timestamp:(CMTime)timestamp
fromSource:(MPPInputSource*)source {
if (source != _cameraSource) {
NSLog(@"Unknown source: %@", source);
return;
}
// Display the captured image on the screen.
CFRetain(imageBuffer);
dispatch_async(dispatch_get_main_queue(), ^{
[_renderer renderPixelBuffer:imageBuffer];
CFRelease(imageBuffer);
});
}
Bu, MPPInputSource için bir yetki verme yöntemidir. İlk olarak, hesabın doğru
doğru kaynaktan (_cameraSource) kareler alınıyor. Daha sonra
ana sıradaki _renderer aracılığıyla kameradan alınan kare.
Şimdi, kareleri görüntülemek için görünüm açılır açılmaz kamerayı başlatmamız gerekiyor.
az sonra görünür. Bunu yapmak için,
viewWillAppear:(BOOL)animated işlevi:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
Kamerayı çalıştırmaya başlamadan önce, kameraya erişmek için kullanıcının iznini almamız gerekir.
MPPCameraInputSource, bir işlev sağlar
Kullanıcı aşağıdaki durumda kamera erişimi istemek ve bir işlem yapmak için requestCameraAccessWithCompletionHandler:(void (^_Nullable)(BOOL
granted))handler
yanıt verdi. Şu kodu viewWillAppear:animated alanına ekleyin:
[_cameraSource requestCameraAccessWithCompletionHandler:^void(BOOL granted) {
if (granted) {
dispatch_async(_videoQueue, ^{
[_cameraSource start];
});
}
}];
Uygulamayı derlemeden önce BUILD dosyanıza aşağıdaki bağımlılıkları ekleyin.
dosya:
sdk_frameworks = [
"AVFoundation",
"CoreGraphics",
"CoreMedia",
],
deps = [
"//mediapipe/objc:mediapipe_framework_ios",
"//mediapipe/objc:mediapipe_input_sources_ios",
"//mediapipe/objc:mediapipe_layer_renderer",
],
Şimdi uygulamayı iOS cihazınızda derleyip çalıştırın. Burada canlı bir kamera görüntüleme feed'ini etkinleştirin.
Artık kamera çerçevelerini MediaPipe grafiğinde kullanmaya hazırız.
iOS'te bir MediaPipe grafiği kullanma
İlgili bağımlılıkları ekleyin
Şunu içeren bir dosya içeren MediaPipe çerçevesi kodunun bağımlılıklarını
MediaPipe grafiği kullanmak için
iOS API'ye bakalım. Bir MediaPipe grafiğini kullanmak için, bir
kullanmayı planladığımız grafiğe bağımlılığımızı
söyleyebiliriz. Aşağıdakileri ekleyin:
satırı, BUILD dosyanızdaki data listesine ekleyin:
"//mediapipe/graphs/edge_detection:mobile_gpu_binary_graph",
Şimdi bağımlılığı, bu grafikte kullanılan hesaplayıcıların deps alanına ekleyin.
BUILD dosyasında:
"//mediapipe/graphs/edge_detection:mobile_calculators",
Son olarak, desteği desteklemek için ViewController.m dosyasını ViewController.mm olarak yeniden adlandırın
Amaç-C++.
ViewController uygulamasında grafiği kullanın
ViewController.m içine aşağıdaki içe aktarma satırını ekleyin:
#import "mediapipe/objc/MPPGraph.h"
Grafiğin adı, giriş akışı ve çıkış akışı:
static NSString* const kGraphName = @"mobile_gpu";
static const char* kInputStream = "input_video";
static const char* kOutputStream = "output_video";
Aşağıdaki özelliği ViewController arayüzüne ekleyin:
// The MediaPipe graph currently in use. Initialized in viewDidLoad, started in viewWillAppear: and
// sent video frames on _videoQueue.
@property(nonatomic) MPPGraph* mediapipeGraph;
Yukarıdaki yorumda açıklandığı gibi, bu grafiği
Önce viewDidLoad. Bunu yapmak için grafiği .pbtxt dosyasından yüklememiz gerekir.
kullanarak aşağıdaki işlevi kullanabilirsiniz:
+ (MPPGraph*)loadGraphFromResource:(NSString*)resource {
// Load the graph config resource.
NSError* configLoadError = nil;
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
if (!resource || resource.length == 0) {
return nil;
}
NSURL* graphURL = [bundle URLForResource:resource withExtension:@"binarypb"];
NSData* data = [NSData dataWithContentsOfURL:graphURL options:0 error:&configLoadError];
if (!data) {
NSLog(@"Failed to load MediaPipe graph config: %@", configLoadError);
return nil;
}
// Parse the graph config resource into mediapipe::CalculatorGraphConfig proto object.
mediapipe::CalculatorGraphConfig config;
config.ParseFromArray(data.bytes, data.length);
// Create MediaPipe graph with mediapipe::CalculatorGraphConfig proto object.
MPPGraph* newGraph = [[MPPGraph alloc] initWithGraphConfig:config];
[newGraph addFrameOutputStream:kOutputStream outputPacketType:MPPPacketTypePixelBuffer];
return newGraph;
}
viewDidLoad içindeki grafiği şu şekilde başlatmak için bu işlevi kullanın:
self.mediapipeGraph = [[self class] loadGraphFromResource:kGraphName];
Grafik, kamera çerçevelerini işlemenin sonuçlarını
ViewController Grafiği başlattıktan sonra
mediapipeGraph nesnesinin yetki verilmiş kullanıcısı olarak ViewController:
self.mediapipeGraph.delegate = self;
Canlı video feed'indeki kareleri işlerken bellek çakışmasını önlemek için şu satırı ekleyin:
// Set maxFramesInFlight to a small value to avoid memory contention for real-time processing.
self.mediapipeGraph.maxFramesInFlight = 2;
Şimdi, kullanıcı kamerayı kullanma izni verdiğinde grafiği başlatın inceleyebilirsiniz:
[_cameraSource requestCameraAccessWithCompletionHandler:^void(BOOL granted) {
if (granted) {
// Start running self.mediapipeGraph.
NSError* error;
if (![self.mediapipeGraph startWithError:&error]) {
NSLog(@"Failed to start graph: %@", error);
}
else if (![self.mediapipeGraph waitUntilIdleWithError:&error]) {
NSLog(@"Failed to complete graph initial run: %@", error);
}
dispatch_async(_videoQueue, ^{
[_cameraSource start];
});
}
}];
Daha önce, processVideoFrame içindeki kameradan kareler aldığımızda
işlevinde, _renderer kullanarak bunları _liveView içinde görüntüledik. Artık
ve bunun yerine bu kareleri grafiğe gönderip sonuçları
oluşturmanız gerekir. Değiştir
işlevini kullanarak şunları yapabilirsiniz:
- (void)processVideoFrame:(CVPixelBufferRef)imageBuffer
timestamp:(CMTime)timestamp
fromSource:(MPPInputSource*)source {
if (source != _cameraSource) {
NSLog(@"Unknown source: %@", source);
return;
}
[self.mediapipeGraph sendPixelBuffer:imageBuffer
intoStream:kInputStream
packetType:MPPPacketTypePixelBuffer];
}
imageBuffer öğesini self.mediapipeGraph adresine tür bir paket olarak göndeririz
MPPPacketTypePixelBuffer, kInputStream giriş akışına eklenir.
"input_video".
Grafik, bu giriş paketiyle çalışır ve şu sonucu verir:
kOutputStream, ör. "çıkış_video". Aşağıdaki temsilciyi uygulayabiliriz
yöntemlerini kullanın:
- (void)mediapipeGraph:(MPPGraph*)graph
didOutputPixelBuffer:(CVPixelBufferRef)pixelBuffer
fromStream:(const std::string&)streamName {
if (streamName == kOutputStream) {
// Display the captured image on the screen.
CVPixelBufferRetain(pixelBuffer);
dispatch_async(dispatch_get_main_queue(), ^{
[_renderer renderPixelBuffer:pixelBuffer];
CVPixelBufferRelease(pixelBuffer);
});
}
}
ViewController öğesinin arayüz tanımını MPPGraphDelegate ile güncelleyin:
@interface ViewController () <MPPGraphDelegate, MPPInputSourceDelegate>
Hepsi bu kadar! Uygulamayı iOS cihazınızda derleyip çalıştırın. Burada sonuçlarını görebilirsiniz. Tebrikler!

iOS örneklerinin artık yaygın bir şablon uygulaması kullandığını unutmayın. Bu işlemde
bu eğitim, common şablon uygulamasında kullanılır. helloworld uygulamasında
bağımlılık grafiği için uygun BUILD dosya bağımlılıklarını