ওহে বিশ্ব! iOS-এ

ভূমিকা

এই হ্যালো ওয়ার্ল্ড! টিউটোরিয়াল একটি iOS অ্যাপ্লিকেশন বিকাশ করতে MediaPipe ফ্রেমওয়ার্ক ব্যবহার করে যা iOS এ একটি MediaPipe গ্রাফ চালায়।

যা আপনি নির্মাণ করবেন

একটি iOS ডিভাইসে একটি লাইভ ভিডিও স্ট্রিমে প্রয়োগ করা রিয়েল-টাইম সোবেল প্রান্ত সনাক্তকরণের জন্য একটি সাধারণ ক্যামেরা অ্যাপ।

edge_detection_ios_gpu_gif

সেটআপ

  1. আপনার সিস্টেমে MediaPipe ফ্রেমওয়ার্ক ইনস্টল করুন, বিস্তারিত জানার জন্য ফ্রেমওয়ার্ক ইনস্টলেশন গাইড দেখুন।
  2. বিকাশের জন্য আপনার iOS ডিভাইস সেটআপ করুন।
  3. iOS অ্যাপ তৈরি এবং স্থাপন করতে আপনার সিস্টেমে Bazel সেটআপ করুন।

প্রান্ত সনাক্তকরণের জন্য গ্রাফ

আমরা নিম্নলিখিত গ্রাফটি ব্যবহার করব, 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"
}

গ্রাফের একটি ভিজ্যুয়ালাইজেশন নীচে দেখানো হয়েছে:

edge_detection_mobile_gpu

এই গ্রাফটিতে একটি একক ইনপুট স্ট্রীম রয়েছে যার নাম input_video সমস্ত আগত ফ্রেমের জন্য যা আপনার ডিভাইসের ক্যামেরা দ্বারা সরবরাহ করা হবে৷

গ্রাফের প্রথম নোড, LuminanceCalculator , একটি একক প্যাকেট (ইমেজ ফ্রেম) নেয় এবং একটি OpenGL শেডার ব্যবহার করে লুমিন্যান্সে পরিবর্তন প্রয়োগ করে। ফলস্বরূপ ইমেজ ফ্রেম luma_video আউটপুট স্ট্রীমে পাঠানো হয়।

দ্বিতীয় নোড, SobelEdgesCalculator luma_video স্ট্রিমে ইনকামিং প্যাকেটগুলিতে প্রান্ত সনাক্তকরণ প্রয়োগ করে এবং output_video আউটপুট স্ট্রীমে ফলাফল দেয়।

আমাদের iOS অ্যাপ্লিকেশন output_video স্ট্রিমের আউটপুট ইমেজ ফ্রেম প্রদর্শন করবে।

প্রাথমিক ন্যূনতম অ্যাপ্লিকেশন সেটআপ

আমরা প্রথমে একটি সাধারণ iOS অ্যাপ্লিকেশন দিয়ে শুরু করি এবং এটি তৈরি করতে bazel কীভাবে ব্যবহার করতে হয় তা প্রদর্শন করি।

প্রথমে, ফাইল > নতুন > একক দৃশ্য অ্যাপের মাধ্যমে একটি XCode প্রকল্প তৈরি করুন।

পণ্যের নামটি "HelloWorld" এ সেট করুন এবং একটি উপযুক্ত প্রতিষ্ঠান শনাক্তকারী ব্যবহার করুন, যেমন com.google.mediapipe । পণ্যের নামের সাথে প্রতিষ্ঠান শনাক্তকারী হবে অ্যাপ্লিকেশনটির জন্য bundle_id , যেমন com.google.mediapipe.HelloWorld

অবজেক্টিভ-সি-তে ভাষা সেট করুন।

একটি উপযুক্ত স্থানে প্রকল্প সংরক্ষণ করুন. আসুন এটিকে $PROJECT_TEMPLATE_LOC কল করি। সুতরাং আপনার প্রকল্পটি $PROJECT_TEMPLATE_LOC/HelloWorld ডিরেক্টরিতে থাকবে৷ এই ডিরেক্টরিতে HelloWorld নামে আরেকটি ডিরেক্টরি এবং একটি HelloWorld.xcodeproj ফাইল থাকবে।

HelloWorld.xcodeproj এই টিউটোরিয়ালের জন্য উপযোগী হবে না, কারণ আমরা iOS অ্যাপ্লিকেশন তৈরি করতে ব্যাজেল ব্যবহার করব। $PROJECT_TEMPLATE_LOC/HelloWorld/HelloWorld ডিরেক্টরির বিষয়বস্তু নীচে তালিকাভুক্ত করা হয়েছে:

  1. AppDelegate.h এবং AppDelegate.m
  2. ViewController.h এবং ViewController.m
  3. main.m
  4. Info.plist
  5. Main.storyboard এবং Launch.storyboard
  6. Assets.xcassets ডিরেক্টরি।

মিডিয়াপাইপ ফ্রেমওয়ার্ক সোর্স কোড অ্যাক্সেস করতে পারে এমন একটি অবস্থানে এই ফাইলগুলিকে HelloWorld নামের একটি ডিরেক্টরিতে অনুলিপি করুন৷ উদাহরণস্বরূপ, আমরা এই টিউটোরিয়ালে যে অ্যাপ্লিকেশনটি তৈরি করব তার সোর্স কোডটি mediapipe/examples/ios/HelloWorld এ অবস্থিত। আমরা কোডল্যাব জুড়ে এই পথটিকে $APPLICATION_PATH হিসাবে উল্লেখ করব।

$APPLICATION_PATH এ একটি BUILD ফাইল তৈরি করুন এবং নিম্নলিখিত বিল্ড নিয়মগুলি যোগ করুন:

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 নিয়ম AppDelegate এবং ViewController ক্লাস, main.m এবং অ্যাপ্লিকেশন স্টোরিবোর্ডের জন্য নির্ভরতা যোগ করে। টেমপ্লেট করা অ্যাপটি শুধুমাত্র UIKit SDK-এর উপর নির্ভর করে।

ios_application নিয়মটি আপনার iOS ডিভাইসে ইনস্টলেশনের জন্য একটি iOS অ্যাপ্লিকেশন তৈরি করতে তৈরি করা HelloWorldAppLibrary অবজেক্টিভ-সি লাইব্রেরি ব্যবহার করে।

অ্যাপটি তৈরি করতে, একটি টার্মিনালে নিম্নলিখিত কমান্ডটি ব্যবহার করুন:

bazel build -c opt --config=ios_arm64 <$APPLICATION_PATH>:HelloWorldApp'

উদাহরণস্বরূপ, mediapipe/examples/ios/helloworldHelloWorldApp অ্যাপ্লিকেশন তৈরি করতে, নিম্নলিখিত কমান্ডটি ব্যবহার করুন:

bazel build -c opt --config=ios_arm64 mediapipe/examples/ios/helloworld:HelloWorldApp

তারপরে, XCode-এ ফিরে যান, উইন্ডো > ডিভাইস এবং সিমুলেটর খুলুন, আপনার ডিভাইস নির্বাচন করুন এবং আপনার ডিভাইসে উপরের কমান্ড দ্বারা তৈরি করা .ipa ফাইল যোগ করুন। এখানে iOS ফ্রেমওয়ার্ক অ্যাপস সেট আপ এবং কম্পাইল করার নথি রয়েছে।

আপনার ডিভাইসে অ্যাপ্লিকেশন খুলুন. যেহেতু এটি খালি, এটি একটি ফাঁকা সাদা পর্দা প্রদর্শন করা উচিত।

লাইভ ভিউ ফিডের জন্য ক্যামেরা ব্যবহার করুন

এই টিউটোরিয়ালে, আমরা MPPCameraInputSource ক্লাস ব্যবহার করব ক্যামেরা থেকে ফ্রেমগুলি অ্যাক্সেস করতে এবং ধরতে। এই ক্লাস ক্যামেরা থেকে ফ্রেম পেতে AVCaptureSession API ব্যবহার করে।

কিন্তু এই ক্লাসটি ব্যবহার করার আগে, অ্যাপে ক্যামেরা ব্যবহার সমর্থন করতে Info.plist ফাইলটি পরিবর্তন করুন।

ViewController.m এ, নিম্নলিখিত আমদানি লাইন যোগ করুন:

#import "mediapipe/objc/MPPCameraInputSource.h"

একটি অবজেক্ট _cameraSource তৈরি করতে এর বাস্তবায়ন ব্লকে নিম্নলিখিত যোগ করুন:

@implementation ViewController {
  // Handles camera access via AVCaptureSession library.
  MPPCameraInputSource* _cameraSource;
}

viewDidLoad() করতে নিম্নলিখিত কোড যোগ করুন:

-(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;
}

কোডটি _cameraSource সূচনা করে, ক্যাপচার সেশন প্রিসেট সেট করে এবং কোন ক্যামেরা ব্যবহার করতে হবে।

আমাদের _cameraSource থেকে আমাদের অ্যাপ্লিকেশন ViewController ফ্রেমগুলি প্রদর্শন করতে হবে। MPPCameraInputSource হল MPPInputSource এর একটি সাবক্লাস, যা তার প্রতিনিধিদের জন্য একটি প্রোটোকল প্রদান করে, যথা MPPInputSourceDelegate । তাই আমাদের অ্যাপ্লিকেশন ViewController _cameraSource এর প্রতিনিধি হতে পারে।

সেই অনুযায়ী ViewController ইন্টারফেস সংজ্ঞা আপডেট করুন:

@interface ViewController () <MPPInputSourceDelegate>

ক্যামেরা সেটআপ পরিচালনা করতে এবং ইনকামিং ফ্রেমগুলি প্রক্রিয়া করতে, আমাদের মূল সারির থেকে আলাদা একটি সারি ব্যবহার করা উচিত। ViewController বাস্তবায়ন ব্লকে নিম্নলিখিত যোগ করুন:

// Process camera frames on this queue.
dispatch_queue_t _videoQueue;

viewDidLoad() এ, _cameraSource অবজেক্ট শুরু করার পরে নিম্নলিখিত লাইন যোগ করুন:

[_cameraSource setDelegate:self queue:_videoQueue];

এবং _cameraSource অবজেক্ট সেট আপ করার আগে সারি শুরু করতে নিম্নলিখিত কোড যোগ করুন:

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

আমরা ক্যামেরা ফ্রেম প্রক্রিয়াকরণের জন্য অগ্রাধিকার QOS_CLASS_USER_INTERACTIVE সহ একটি সিরিয়াল সারি ব্যবহার করব৷

ViewController এর ইন্টারফেস/বাস্তবায়নের আগে ফাইলের শীর্ষে হেডার আমদানি করার পরে নিম্নলিখিত লাইনটি যোগ করুন:

static const char* kVideoQueueLabel = "com.google.mediapipe.example.videoQueue";

MPPInputSourceDelegate প্রোটোকল থেকে কোনো পদ্ধতি প্রয়োগ করার আগে, আমাদের প্রথমে ক্যামেরা ফ্রেমগুলি প্রদর্শনের একটি উপায় সেট আপ করতে হবে। মিডিয়াপাইপ ফ্রেমওয়ার্ক স্ক্রীনে ছবি প্রদর্শনের জন্য MPPLayerRenderer নামে আরেকটি ইউটিলিটি প্রদান করে। এই ইউটিলিটিটি CVPixelBufferRef অবজেক্টগুলি প্রদর্শন করতে ব্যবহার করা যেতে পারে, যা MPPCameraInputSource দ্বারা তার প্রতিনিধিদের দেওয়া চিত্রগুলির ধরন।

ViewController.m এ, নিম্নলিখিত আমদানি লাইন যোগ করুন:

#import "mediapipe/objc/MPPLayerRenderer.h"

স্ক্রিনের চিত্রগুলি প্রদর্শন করতে, আমাদের ViewController _liveView নামে একটি নতুন UIView অবজেক্ট যুক্ত করতে হবে।

ViewController বাস্তবায়ন ব্লকে নিম্নলিখিত লাইনগুলি যুক্ত করুন:

// Display the camera preview frames.
IBOutlet UIView* _liveView;
// Render frames in a layer.
MPPLayerRenderer* _renderer;

Main.storyboard এ যান, অবজেক্ট লাইব্রেরি থেকে ViewController ক্লাসের View একটি UIView অবজেক্ট যোগ করুন। এই ভিউ থেকে _liveView অবজেক্টে একটি রেফারেন্সিং আউটলেট যোগ করুন যা আপনি এইমাত্র ViewController ক্লাসে যোগ করেছেন। দৃশ্যটির আকার পরিবর্তন করুন যাতে এটি কেন্দ্রীভূত হয় এবং পুরো অ্যাপ্লিকেশন স্ক্রীনকে কভার করে।

ViewController.m এ ফিরে যান এবং _renderer অবজেক্ট শুরু করতে viewDidLoad() এ নিম্নলিখিত কোড যোগ করুন:

_renderer = [[MPPLayerRenderer alloc] init];
_renderer.layer.frame = _liveView.layer.bounds;
[_liveView.layer addSublayer:_renderer.layer];
_renderer.frameScaleMode = MPPFrameScaleModeFillAndCrop;

ক্যামেরা থেকে ফ্রেম পেতে, আমরা নিম্নলিখিত পদ্ধতি প্রয়োগ করব:

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

এটি MPPInputSource এর একটি প্রতিনিধি পদ্ধতি। আমরা প্রথমে চেক করি যে আমরা সঠিক উৎস থেকে ফ্রেম পাচ্ছি, অর্থাৎ _cameraSource । তারপরে আমরা মূল সারিতে _renderer এর মাধ্যমে ক্যামেরা থেকে প্রাপ্ত ফ্রেমটি প্রদর্শন করি।

এখন, ফ্রেমগুলি প্রদর্শনের দৃশ্যটি প্রদর্শিত হওয়ার সাথে সাথে আমাদের ক্যামেরা চালু করতে হবে। এটি করার জন্য, আমরা viewWillAppear:(BOOL)animated ফাংশন বাস্তবায়ন করব:

-(void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
}

আমরা ক্যামেরা চালানো শুরু করার আগে, এটি অ্যাক্সেস করার জন্য আমাদের ব্যবহারকারীর অনুমতি প্রয়োজন। MPPCameraInputSource একটি ফাংশন অনুরোধ প্রদান করে requestCameraAccessWithCompletionHandler:(void (^_Nullable)(BOOL granted))handler ক্যামেরা অ্যাক্সেসের অনুরোধ করতে এবং ব্যবহারকারীর প্রতিক্রিয়া জানালে কিছু কাজ করতে। viewWillAppear:animated করতে নিম্নলিখিত কোড যোগ করুন:

[_cameraSource requestCameraAccessWithCompletionHandler:^void(BOOL granted) {
  if (granted) {
    dispatch_async(_videoQueue, ^{
      [_cameraSource start];
    });
  }
}];

অ্যাপ্লিকেশন তৈরি করার আগে, আপনার BUILD ফাইলে নিম্নলিখিত নির্ভরতা যুক্ত করুন:

sdk_frameworks = [
    "AVFoundation",
    "CoreGraphics",
    "CoreMedia",
],
deps = [
    "//mediapipe/objc:mediapipe_framework_ios",
    "//mediapipe/objc:mediapipe_input_sources_ios",
    "//mediapipe/objc:mediapipe_layer_renderer",
],

এখন আপনার iOS ডিভাইসে অ্যাপ্লিকেশনটি তৈরি করুন এবং চালান। ক্যামেরা অনুমতি গ্রহণ করার পরে আপনার একটি লাইভ ক্যামেরা ভিউ ফিড দেখতে হবে।

আমরা এখন মিডিয়াপাইপ গ্রাফে ক্যামেরা ফ্রেম ব্যবহার করার জন্য প্রস্তুত।

iOS এ একটি MediaPipe গ্রাফ ব্যবহার করা

প্রাসঙ্গিক নির্ভরতা যোগ করুন

মিডিয়াপাইপ গ্রাফ ব্যবহার করার জন্য আমরা ইতিমধ্যেই MediaPipe ফ্রেমওয়ার্ক কোডের নির্ভরতা যোগ করেছি যাতে iOS API রয়েছে। একটি MediaPipe গ্রাফ ব্যবহার করার জন্য, আমরা আমাদের অ্যাপ্লিকেশনে যে গ্রাফ ব্যবহার করতে চাই তার উপর আমাদের নির্ভরতা যোগ করতে হবে। আপনার BUILD ফাইলে data তালিকায় নিম্নলিখিত লাইনটি যুক্ত করুন:

"//mediapipe/graphs/edge_detection:mobile_gpu_binary_graph",

এখন BUILD ফাইলের deps ক্ষেত্রে এই গ্রাফে ব্যবহৃত ক্যালকুলেটরগুলিতে নির্ভরতা যোগ করুন:

"//mediapipe/graphs/edge_detection:mobile_calculators",

অবশেষে, অবজেক্টিভ-সি++ সমর্থন করতে ViewController.m ফাইলটির নাম পরিবর্তন করে ViewController.mm করুন।

ViewController গ্রাফটি ব্যবহার করুন

ViewController.m এ, নিম্নলিখিত আমদানি লাইন যোগ করুন:

#import "mediapipe/objc/MPPGraph.h"

গ্রাফ, ইনপুট স্ট্রীম এবং আউটপুট স্ট্রীমের নাম সহ একটি স্ট্যাটিক ধ্রুবক ঘোষণা করুন:

static NSString* const kGraphName = @"mobile_gpu";

static const char* kInputStream = "input_video";
static const char* kOutputStream = "output_video";

ViewController ইন্টারফেসে নিম্নলিখিত বৈশিষ্ট্য যোগ করুন:

// The MediaPipe graph currently in use. Initialized in viewDidLoad, started in viewWillAppear: and
// sent video frames on _videoQueue.
@property(nonatomic) MPPGraph* mediapipeGraph;

উপরের মন্তব্যে যেমন ব্যাখ্যা করা হয়েছে, আমরা প্রথমে viewDidLoad এই গ্রাফটি শুরু করব। এটি করার জন্য, আমাদের নিম্নলিখিত ফাংশনটি ব্যবহার করে .pbtxt ফাইল থেকে গ্রাফটি লোড করতে হবে:

+   (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 গ্রাফটি শুরু করতে এই ফাংশনটি ব্যবহার করুন:

self.mediapipeGraph = [[self class] loadGraphFromResource:kGraphName];

গ্রাফটি ক্যামেরা ফ্রেম প্রক্রিয়াকরণের ফলাফলগুলি ViewController ফেরত পাঠাতে হবে। mediapipeGraph অবজেক্টের প্রতিনিধি হিসাবে ViewController সেট করতে গ্রাফটি শুরু করার পরে নিম্নলিখিত লাইনটি যুক্ত করুন:

self.mediapipeGraph.delegate = self;

লাইভ ভিডিও ফিড থেকে ফ্রেম প্রক্রিয়াকরণের সময় স্মৃতি বিবাদ এড়াতে, নিম্নলিখিত লাইন যোগ করুন:

// Set maxFramesInFlight to a small value to avoid memory contention for real-time processing.
self.mediapipeGraph.maxFramesInFlight = 2;

এখন, ব্যবহারকারী আমাদের অ্যাপে ক্যামেরা ব্যবহার করার অনুমতি দিলে গ্রাফটি শুরু করুন:

[_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];
    });
  }
}];

এর আগে, যখন আমরা processVideoFrame ফাংশনে ক্যামেরা থেকে ফ্রেম পেতাম, তখন আমরা সেগুলিকে _renderer ব্যবহার করে _liveView এ প্রদর্শন করতাম। এখন, আমাদের সেই ফ্রেমগুলিকে গ্রাফে পাঠাতে হবে এবং পরিবর্তে ফলাফলগুলি রেন্ডার করতে হবে। নিম্নলিখিত কাজ করতে এই ফাংশনের বাস্তবায়ন পরিবর্তন করুন:

-   (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 self.mediapipeGraphMPPPacketTypePixelBuffer টাইপের একটি প্যাকেট হিসাবে ইনপুট স্ট্রীম kInputStream , অর্থাৎ "input_video"-এ পাঠাই।

গ্রাফটি এই ইনপুট প্যাকেটের সাথে চলবে এবং ফলাফল kOutputStream , অর্থাৎ "output_video"-এ আউটপুট হবে। আমরা এই আউটপুট স্ট্রীমে প্যাকেটগুলি গ্রহণ করতে এবং সেগুলিকে স্ক্রিনে প্রদর্শন করতে নিম্নলিখিত প্রতিনিধি পদ্ধতি প্রয়োগ করতে পারি:

-   (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);
    });
  }
}

MPPGraphDelegate এর সাথে ViewController এর ইন্টারফেস সংজ্ঞা আপডেট করুন:

@interface ViewController () <MPPGraphDelegate, MPPInputSourceDelegate>

এবং যে সব! আপনার iOS ডিভাইসে অ্যাপটি তৈরি করুন এবং চালান। আপনি একটি লাইভ ভিডিও ফিডে প্রান্ত সনাক্তকরণ গ্রাফ চালানোর ফলাফল দেখতে হবে। অভিনন্দন!

edge_detection_ios_gpu_gif

অনুগ্রহ করে মনে রাখবেন যে iOS উদাহরণগুলি এখন একটি সাধারণ টেমপ্লেট অ্যাপ ব্যবহার করে। এই টিউটোরিয়ালের কোডটি সাধারণ টেমপ্লেট অ্যাপে ব্যবহার করা হয়েছে। হ্যালোওয়ার্ল্ড অ্যাপে প্রান্ত সনাক্তকরণ গ্রাফের জন্য উপযুক্ত BUILD ফাইল নির্ভরতা রয়েছে।