Android'de Hello World!

Giriş

Merhaba Dünya! eğiticisi MediaPipe Framework'ü kullanır ve böylece Android'de bir MediaPipe grafiği çalıştırıyor.

Ne oluşturacaksınız?

Canlı bir videoya gerçek zamanlı Sobel kenar algılaması için uygulanan basit bir kamera uygulaması canlı yayın yapabilirsiniz.

edge_detection_android_gpu_gif

Kurulum

  1. Sisteminize MediaPipe Framework'ü yükleme için Çerçeve yüklemesi kurulumuna bakın rehberini inceleyin.
  2. Android Geliştirme SDK'sını ve Android NDK'yı yükleyin. Bunu nasıl yapacağınızı şuradan öğrenebilirsiniz: [Çerçeve kurulum kılavuzu].
  3. Android cihazınızda geliştirici seçeneklerini etkinleştirin.
  4. Android 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 in
# mediapipe/examples/android/src/java/com/mediapipe/apps/basic and
# mediapipe/examples/ios/edgedetectiongpu.

# 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:

edge_detection_mobile_gpu

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.

Android uygulamamız, tablodaki çıktıların resim çerçevelerini output_video akışı.

İlk minimum uygulama kurulumu

Öncelikle, "Hello World!" ifadesini görüntüleyen basit bir Android uygulamasıyla başlıyoruz. ekranda görebilirsiniz. Android cihazlar hakkında bilginiz varsa bu adımı atlayabilirsiniz. bazel kullanan uygulamalar.

Android uygulamanızı oluşturacağınız yeni bir dizin oluşturun. Örneğin, bu eğiticinin tam kodunu şu adreste bulabilirsiniz: mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic Bugün codelab'de bu yoldan $APPLICATION_PATH olarak bahsedin.

Uygulamaya giden yolda:

  • Uygulamanın adı helloworld.
  • Başvuru $PACKAGE_PATH, com.google.mediapipe.apps.basic. Bunlar, bu eğiticideki kod snippet'lerinde kullanıldığından lütfen kendi $PACKAGE_PATH'iniz olur.

$APPLICATION_PATH/res/layout adlı klasöre bir activity_main.xml dosyası ekleyin. Bu sütunda uygulamanın tam ekranında Hello World! dizesine sahip bir TextView:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

$APPLICATION_PATH için, içeriği yükleyen basit bir MainActivity.java ekleyin activity_main.xml düzeninin özelliklerini ayarlayın:

package com.google.mediapipe.apps.basic;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

/** Bare-bones main activity. */
public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}

$APPLICATION_PATH hedefine AndroidManifest.xml adlı bir manifest dosyasını ekleyin. Bu dosya uygulama başlangıcında MainActivity öğesini başlatır:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.mediapipe.apps.basic">

  <uses-sdk
      android:minSdkVersion="19"
      android:targetSdkVersion="19" />

  <application
      android:allowBackup="true"
      android:label="${appName}"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
      <activity
          android:name="${mainActivity}"
          android:exported="true"
          android:screenOrientation="portrait">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>
  </application>

</manifest>

Uygulamamızda, uygulamada bir Theme.AppCompat teması kullanıyoruz. Bu yüzden uygun tema referansları hazırlayın. colors.xml adlı kişiyi şuraya ekle: $APPLICATION_PATH/res/values/:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
</resources>

styles.xml öğesini $APPLICATION_PATH/res/values/ öğesine ekleyin:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

Uygulamayı oluşturmak için $APPLICATION_PATH uygulamasına bir BUILD dosyası ekleyin ve Manifest'teki ${appName} ve ${mainActivity}, dizelerle değiştirilecek aşağıda gösterildiği gibi BUILD içinde belirtilir.

android_library(
    name = "basic_lib",
    srcs = glob(["*.java"]),
    manifest = "AndroidManifest.xml",
    resource_files = glob(["res/**"]),
    deps = [
        "//third_party:android_constraint_layout",
        "//third_party:androidx_appcompat",
    ],
)

android_binary(
    name = "helloworld",
    manifest = "AndroidManifest.xml",
    manifest_values = {
        "applicationId": "com.google.mediapipe.apps.basic",
        "appName": "Hello World",
        "mainActivity": ".MainActivity",
    },
    multidex = "native",
    deps = [
        ":basic_lib",
    ],
)

android_library kuralı, kaynak dosyalara MainActivity için bağımlılık ekler. ve AndroidManifest.xml.

android_binary kuralı, şu işlemler için oluşturulan basic_lib Android kitaplığını kullanır: Android cihazınıza yüklemek üzere bir ikili program APK'sı derleme

Uygulamayı derlemek için aşağıdaki komutu kullanın:

bazel build -c opt --config=android_arm64 $APPLICATION_PATH:helloworld

Oluşturulan APK dosyasını adb install kullanarak yükleyin. Örneğin:

adb install bazel-bin/$APPLICATION_PATH/helloworld.apk

Cihazınızda uygulamayı açın. Metnin yer aldığı bir ekran görüntülenmelidir. Hello World!

bazel_hello_world_android

Kamera CameraX üzerinden kullanılıyor

Kamera İzinleri

Kamerayı uygulamamızda kullanmak için kullanıcıdan erişebilir. Kamera izni istemek için aşağıdakileri ekleyin: AndroidManifest.xml:

<!-- For using the camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

Şu öğede minimum SDK sürümünü 21 ve hedef SDK sürümünü 27 olarak değiştirin: aynı dosya:

<uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="27" />

Bu işlem, kullanıcıdan kamera izni istemesini sağlar ve kamera erişimi için CameraX kitaplığını kullanmamız gerekiyor.

Kamera izni istemek için MediaPipe Framework tarafından sağlanan bir yardımcı programı kullanabiliriz yani PermissionHelper bileşenlerini kullanabilirsiniz. Kullanmak için bir bağımlılık ekleyin "//mediapipe/java/com/google/mediapipe/components:android_components" BUILD içinde mediapipe_lib kural.

PermissionHelper öğesini MainActivity içinde kullanmak için aşağıdaki satırı onCreate işlevi:

PermissionHelper.checkAndRequestCameraPermissions(this);

Bu işlemle, ekranda bir iletişim kutusuyla kullanıcıdan kamerayı bu uygulamada kullanabilirsiniz.

Kullanıcı yanıtını işlemek için aşağıdaki kodu ekleyin:

@Override
public void onRequestPermissionsResult(
    int requestCode, String[] permissions, int[] grantResults) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  PermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
protected void onResume() {
  super.onResume();
  if (PermissionHelper.cameraPermissionsGranted(this)) {
    startCamera();
  }
}

public void startCamera() {}

startCamera() yöntemini şimdilik boş bırakacağız. Kullanıcı yanıt verdiğinde komut isteminde MainActivity devam ettirilir ve onResume() çağrılır. Kod, kamerayı kullanma izinlerinin verildiğini ve ve ardından kamerayı başlatır.

Uygulamayı yeniden derleyip yükleyin. Şimdi bir istem görebilirsiniz. uygulamanın kameraya erişmesine izin verir.

Kamera erişimi

Kamera izinlerini kullanarak kareleri şuradan başlatıp getirebiliriz: bulun.

Kareleri kameradan görüntülemek için bir SurfaceView kullanacağız. Her bir kare SurfaceTexture bir nesne içinde depolanır. Bunları kullanmak için öncelikle uygulamamızın düzenini değiştirmemiz gerekiyor.

TextView kod bloğunun tamamını şuradan kaldırın: $APPLICATION_PATH/res/layout/activity_main.xml ve aşağıdaki kodu ekleyin aşağıdaki adımları uygulayabilirsiniz:

<FrameLayout
    android:id="@+id/preview_display_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1">
    <TextView
        android:id="@+id/no_camera_access_view"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:gravity="center"
        android:text="@string/no_camera_access" />
</FrameLayout>

Bu kod bloğunda preview_display_layout adında yeni bir FrameLayout ve TextView, no_camera_access_preview adlı bunun içine yerleştirilmiş. Kamera olduğunda olmadığı için, uygulamamız bu iznin başarılı bir şekilde Dize mesajıyla birlikte, no_camera_access değişkeninde depolanır. TextView $APPLICATION_PATH/res/values/strings.xml dosyasına aşağıdaki satırı ekleyin:

<string name="no_camera_access" translatable="false">Please grant camera permissions.</string>

Kullanıcı kamera izni vermediğinde ekran artık şu şekilde görünür: bu:

missing_camera_permission_android

Şimdi SurfaceTexture ve SurfaceView nesnelerini şuraya ekleyeceğiz: MainActivity:

private SurfaceTexture previewFrameTexture;
private SurfaceView previewDisplayView;

onCreate(Bundle) işlevinde, aşağıdaki iki satırı önce ekleyin kamera izinleri isteniyor:

previewDisplayView = new SurfaceView(this);
setupPreviewDisplayView();

Şimdi de setupPreviewDisplayView() öğesini tanımlayan kodu ekleyin:

private void setupPreviewDisplayView() {
  previewDisplayView.setVisibility(View.GONE);
  ViewGroup viewGroup = findViewById(R.id.preview_display_layout);
  viewGroup.addView(previewDisplayView);
}

Yeni bir SurfaceView nesnesi tanımlar ve bunu Görüntülemek için kullanabileceğimiz preview_display_layout FrameLayout nesnesi kamera karelerini previewFrameTexture adlı bir SurfaceTexture nesnesi kullanarak oluşturun.

Kamera çerçevelerini almak üzere previewFrameTexture işlevini kullanmak için CameraX kullanılır. Çerçeve, CameraX'i kullanmak için CameraXPreviewHelper adlı bir yardımcı program sağlar. Bu sınıf, kamera şunun üzerinden başlatıldığında bir dinleyiciyi günceller: onCameraStarted(@Nullable SurfaceTexture)

Bu yardımcı programı kullanmak için BUILD dosyasını değiştirerek "//mediapipe/java/com/google/mediapipe/components:android_camerax_helper".

Şimdi CameraXPreviewHelper dosyasını içe aktarın ve aşağıdaki satırı MainActivity:

private CameraXPreviewHelper cameraHelper;

Artık uygulamamızı startCamera() öğesine ekleyebiliriz:

public void startCamera() {
  cameraHelper = new CameraXPreviewHelper();
  cameraHelper.setOnCameraStartedListener(
    surfaceTexture -> {
      previewFrameTexture = surfaceTexture;
      // Make the display view visible to start showing the preview.
      previewDisplayView.setVisibility(View.VISIBLE);
    });
}

Bu işlem yeni bir CameraXPreviewHelper nesnesi oluşturur ve anonim bir nesne ekler bahsedeceğim. cameraHelper, kameranın başladığını bildirdiğinde ve kareleri tutmak için bir surfaceTexture varsa, previewFrameTexture olarak surfaceTexture ve previewDisplayView turuna katılın kadrajı previewFrameTexture biçiminden görmeye başlayabilmemiz için görünür.

Ancak, kamerayı başlatmadan önce, hangi kamerayı başlatacağımıza pek de iyi olmadığını unutmayın. CameraXPreviewHelper, iki sağlayan CameraHelper kaynağından devralır seçenekler, FRONT ve BACK. Kararı BUILD dosyasından iletebiliriz. başka bir sürümünü oluşturmak için kod değişikliğinin gerekli olmadığı meta veriler başka bir kamera kullanarak uygulamayı başlatabilirsiniz.

Canlı bir sahnede kenar algılama işlemi yapmak için BACK kamerayı kullanmak istediğimizi varsayarsak meta verileri AndroidManifest.xml dosyasına ekleyin:

      ...
      <meta-data android:name="cameraFacingFront" android:value="${cameraFacingFront}"/>
  </application>
</manifest>

ve helloworld Android ikili kuralında BUILD içinde seçimi belirtin manifest_values alanında yeni bir girişle:

manifest_values = {
    "applicationId": "com.google.mediapipe.apps.basic",
    "appName": "Hello World",
    "mainActivity": ".MainActivity",
    "cameraFacingFront": "False",
},

Şimdi, manifest_values politikasında belirtilen meta verileri almak için MainActivity ürününde, ApplicationInfo nesnesi ekleyin:

private ApplicationInfo applicationInfo;

onCreate() işlevine şunu ekleyin:

try {
  applicationInfo =
      getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
  Log.e(TAG, "Cannot find application info: " + e);
}

Şimdi startCamera() işlevinin sonuna aşağıdaki satırı ekleyin:

CameraHelper.CameraFacing cameraFacing =
    applicationInfo.metaData.getBoolean("cameraFacingFront", false)
        ? CameraHelper.CameraFacing.FRONT
        : CameraHelper.CameraFacing.BACK;
cameraHelper.startCamera(this, cameraFacing, /*unusedSurfaceTexture=*/ null);

Bu noktada, uygulamanın başarıyla derlenmesi gerekir. Ancak, üzerinde çalışırken, siyah bir ekran görürsünüz (kamerayı takiben için izin verildi.) Çünkü her ne kadar CameraXPreviewHelper tarafından sağlanan surfaceTexture değişkeni previewSurfaceView, çıkışını kullanmıyor ve henüz ekranda gösteriyor.

Çerçeveleri bir MediaPipe grafiğinde kullanmak istediğimiz için doğrudan bu eğiticide kamera çıkışını görüntüleyebilirsiniz. Bunun yerine, işlenmek üzere kamera çerçevelerini bir MediaPipe grafiğine gönderebilir ve grafiğin çıkışını inceleyin.

ExternalTextureConverter kurulumu

SurfaceTexture, bir akıştan görüntü karelerini OpenGL ES olarak yakalar dokunun. Bir MediaPipe grafiğini kullanmak için, kameradan alınan kareler normal bir Open GL doku nesnesinde saklanır. Çerçeve bir sınıf sağlar, SurfaceTexture klasöründe depolanan resmi dönüştürmek için ExternalTextureConverter nesnesine dönüştürmenize gerek yoktur.

ExternalTextureConverter aracını kullanmak için bir EGLContext öğesine de ihtiyacımız var. EglManager nesnesi tarafından oluşturulur ve yönetilir. BUILD öğesine bağımlılık ekleyin EglManager, "//mediapipe/java/com/google/mediapipe/glutil" kullanılacak dosya.

MainActivity içinde aşağıdaki beyanları ekleyin:

private EglManager eglManager;
private ExternalTextureConverter converter;

onCreate(Bundle) işlevinde, Kamera izinleri istenmeden önce eglManager nesne:

eglManager = new EglManager(null);

Bu işlemi onaylamak için MainActivity fonksiyonunda onResume() işlevini tanımladığımızı unutmayın. kamera izinleri verildi ve startCamera() numaralı telefonu arayın. Bundan önce kontrol, converter işlemini başlatmak için onResume() içine aşağıdaki satırı ekleyin nesne:

converter = new ExternalTextureConverter(eglManager.getContext());

Bu converter artık eglManager tarafından yönetilen GLContext kullanıyor.

Aynı zamanda, MainActivity içinde onPause() işlevini geçersiz kılmamız gerekir. Uygulama duraklatılmış duruma geçerse converter düzgün bir şekilde kapatılır:

@Override
protected void onPause() {
  super.onPause();
  converter.close();
}

previewFrameTexture çıkışını converter öğesine aktarmak için setupPreviewDisplayView() için takip eden kod bloğu:

previewDisplayView
 .getHolder()
 .addCallback(
     new SurfaceHolder.Callback() {
       @Override
       public void surfaceCreated(SurfaceHolder holder) {}

       @Override
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
         // (Re-)Compute the ideal size of the camera-preview display (the area that the
         // camera-preview frames get rendered onto, potentially with scaling and rotation)
         // based on the size of the SurfaceView that contains the display.
         Size viewSize = new Size(width, height);
         Size displaySize = cameraHelper.computeDisplaySizeFromViewSize(viewSize);

         // Connect the converter to the camera-preview frames as its input (via
         // previewFrameTexture), and configure the output width and height as the computed
         // display size.
         converter.setSurfaceTextureAndAttachToGLContext(
             previewFrameTexture, displaySize.getWidth(), displaySize.getHeight());
       }

       @Override
       public void surfaceDestroyed(SurfaceHolder holder) {}
     });

Bu kod bloğunda, şuraya özel bir SurfaceHolder.Callback ekleriz: Uygun bir görüntü boyutunu hesaplamak için previewDisplayView ve surfaceChanged(SurfaceHolder holder, int format, int width, int height) işlevini uygulayın. bağlamak ve previewFrameTexture bağlamak için nesnesini tanımlayın ve hesaplanan displaySize öğesinin karelerini converter öğesine gönderin.

Artık kamera çerçevelerini MediaPipe grafiğinde kullanmaya hazırız.

Android'de bir MediaPipe grafiği kullanma

İlgili bağımlılıkları ekleyin

MediaPipe grafiği kullanmak için son olarak MediaPipe çerçevesine bağımlılık eklememiz elde etti. Önce JNI kodunu kullanarak cc_binary oluşturmak için bir derleme kuralı ekleyeceğiz bu ikili programı kullanmak için bir cc_library kuralı derlemek bir yöntem de var. BUILD dosyanıza şu kod bloğunu ekleyin:

cc_binary(
    name = "libmediapipe_jni.so",
    linkshared = 1,
    linkstatic = 1,
    deps = [
        "//mediapipe/java/com/google/mediapipe/framework/jni:mediapipe_framework_jni",
    ],
)

cc_library(
    name = "mediapipe_jni_lib",
    srcs = [":libmediapipe_jni.so"],
    alwayslink = 1,
)

":mediapipe_jni_lib" bağımlılığını şurada mediapipe_lib derleme kuralına ekleyin: BUILD dosyası.

Sonra, kullanmak istediğimiz MediaPipe grafiğine özel bağımlılıklar takip edebilirsiniz.

İlk olarak, libmediapipe_jni.so uygulamasındaki tüm hesap makinesi koduna bağımlılıklar ekleyin derleme kuralı:

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

MediaPipe grafikleri .pbtxt dosyalarıdır, ancak bunları uygulamada kullanmak için .binarypb dosyası oluşturmak için mediapipe_binary_graph derleme kuralını kullanın.

helloworld Android ikili program derleme kuralına mediapipe_binary_graph ekleyin. öğe olarak grafiğe özgü hedefi seçin:

assets = [
  "//mediapipe/graphs/edge_detection:mobile_gpu_binary_graph",
],
assets_dir = "",

assets derleme kuralında TensorFlowLite gibi başka öğeler de ekleyebilirsiniz modellerden bahsetmek istiyorum.

Ayrıcamanifest_values daha sonra MainActivity içinde alınacak şekilde grafik:

manifest_values = {
    "applicationId": "com.google.mediapipe.apps.basic",
    "appName": "Hello World",
    "mainActivity": ".MainActivity",
    "cameraFacingFront": "False",
    "binaryGraphName": "mobile_gpu.binarypb",
    "inputVideoStreamName": "input_video",
    "outputVideoStreamName": "output_video",
},

binaryGraphName işlevinin ikili grafiğin dosya adını gösterdiğini unutmayın. mediapipe_binary_graph hedefindeki output_name alanı tarafından belirlenir. inputVideoStreamName ve outputVideoStreamName, giriş ve çıkıştır sırasıyla grafikte belirtilen video akışı adı.

Şimdi MainActivity öğesinin MediaPipe çerçevesini yüklemesi gerekiyor. Ayrıca, çerçevesi OpenCV'yi kullandığından MainActvity, OpenCV öğesini de yüklemelidir. Şunu kullanın: MainActivity içinde aşağıdaki kodu (sınıfın içinde, herhangi bir işlevin içinde değil) iki bağımlılığı da yükleyebilirsiniz:

static {
  // Load all native libraries needed by the app.
  System.loadLibrary("mediapipe_jni");
  System.loadLibrary("opencv_java3");
}

MainActivity uygulamasında grafiği kullanın

Öncelikle, şuradan derlenen .binarypb öğesini içeren öğeyi yüklememiz gerekir: grafiğin .pbtxt dosyası. Bunun için bir MediaPipe yardımcı programı kullanabiliriz, AndroidAssetUtil.

Başlatmadan önce onCreate(Bundle) içinde öğe yöneticisini başlatın eglManager:

// Initialize asset manager so that MediaPipe native libraries can access the app assets, e.g.,
// binary graphs.
AndroidAssetUtil.initializeNativeAssetManager(this);

Şimdi, kamera çerçeveleri gönderen bir FrameProcessor nesnesi oluşturmamız gerekiyor. converter tarafından MediaPipe grafiğine hazırlanır ve grafiği çalıştırır. ardından previewDisplayView öğesini güncelleyerek çıkışı görüntüler. Ekle FrameProcessor öğesini tanımlamak için şu kodu kullanın:

private FrameProcessor processor;

ve eglManager başlatıldıktan sonra onCreate(Bundle) içinde başlat:

processor =
    new FrameProcessor(
        this,
        eglManager.getNativeContext(),
        applicationInfo.metaData.getString("binaryGraphName"),
        applicationInfo.metaData.getString("inputVideoStreamName"),
        applicationInfo.metaData.getString("outputVideoStreamName"));

processor öğesinin, şunun için converter üzerinden dönüştürülen kareleri kullanması gerekir: bahsedeceğim. Başlattıktan sonra aşağıdaki satırı onResume() öğesine ekleyin converter:

converter.setConsumer(processor);

processor, çıkışı previewDisplayView öğesine göndermelidir. Bunu yapmak için özel SurfaceHolder.Callback için aşağıdaki işlev tanımlarını içerir:

@Override
public void surfaceCreated(SurfaceHolder holder) {
  processor.getVideoSurfaceOutput().setSurface(holder.getSurface());
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
  processor.getVideoSurfaceOutput().setSurface(null);
}

SurfaceHolder oluşturulduğunda, Surface VideoSurfaceOutput / processor. İmha edildikten sonra, processor öğesinin VideoSurfaceOutput.

Hepsi bu kadar! Artık projeyi başarılı bir şekilde derleyip çalıştırabilmeniz gerekir sobel sınır algılama özelliğinin canlı kamerada çalıştığını görün feed! Tebrikler!

edge_detection_android_gpu_gif

Herhangi bir sorunla karşılaşırsanız lütfen eğiticinin tam koduna göz atın. burada bulabilirsiniz.