Giriş
Bu Hello World! eğiticisi, Android'de MediaPipe grafiği çalıştıran bir Android uygulaması geliştirmek için MediaPipe Framework'ü kullanır.
Ne oluşturacaksınız?
Android cihazdaki canlı video akışına gerçek zamanlı Sobel kenar algılama özelliği sağlayan basit bir kamera uygulaması.
Kurulum
- Sisteminize MediaPipe Framework'ü yükleyin. Ayrıntılar için Çerçeve kurulum kılavuzuna bakın.
- Android Geliştirme SDK'sını ve Android NDK'yı yükleyin. Bunu nasıl yapacağınızı [Framework kurulum kılavuzu] bölümünde de bulabilirsiniz.
- Android cihazınızda geliştirici seçeneklerini etkinleştirin.
- Android uygulamasını derlemek ve dağıtmak için sisteminizde Bazel'i kurun.
Kenar algılama grafiği
Kullanılacak grafik 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"
}
Aşağıda grafikle ilgili bir görsel yer almaktadır:
Bu grafikte, cihazınızın kamerası tarafından sağlanacak tüm gelen kareler için input_video
adlı tek bir giriş akışı vardır.
Grafikteki ilk düğüm (LuminanceCalculator
), tek bir paket (görüntü çerçevesi) alır ve OpenGL gölgelendirici kullanarak parlaklık değişikliği uygular. Elde edilen resim çerçevesi, luma_video
çıkış akışına gönderilir.
İkinci düğüm olan SobelEdgesCalculator
, luma_video
akışındaki gelen paketlere uç algılama uygular ve çıkışta output_video
çıkış akışı oluşturur.
Android uygulamamız, output_video
akışının çıktı resmi çerçevelerini gösterir.
Minimum minimum uygulama kurulumu
İlk olarak, ekranda "Hello World!" yazan basit bir Android uygulamasıyla başlıyoruz. bazel
kullanarak Android uygulamaları oluşturma konusunda bilgi sahibiyseniz bu adımı atlayabilirsiniz.
Android uygulamanızı oluşturacağınız yeni bir dizin oluşturun. Örneğin, bu eğitimin tüm kodunu mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic
adresinde bulabilirsiniz. Codelab'de bu yol $APPLICATION_PATH
olarak kullanılacaktır.
Uygulamaya giden yolda şunları unutmayın:
- Uygulamanın adı
helloworld
. - Uygulamanın
$PACKAGE_PATH
özelliğicom.google.mediapipe.apps.basic
. Bu ad, bu eğiticideki kod snippet'lerinde kullanılmaktadır. Bu nedenle, kod snippet'lerini kopyaladığınızda/kullandığınızda kendi$PACKAGE_PATH
öğenizi kullanmayı lütfen unutmayın.
$APPLICATION_PATH/res/layout
hedefine bir activity_main.xml
dosyası ekleyin. Uygulamanın tam ekranında Hello
World!
dizesiyle bir TextView
görüntülenir:
<?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
öğesine, activity_main.xml
düzeninin içeriğini aşağıda gösterildiği gibi yükleyen basit bir MainActivity.java
ekleyin:
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
uygulamasına, AndroidManifest.xml
adlı manifest dosyası ekleyin. Uygulama başladığında MainActivity
başlatılı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 Theme.AppCompat
teması kullandığımız için uygun tema referanslarına ihtiyacımız var. colors.xml
adlı kişiyi $APPLICATION_PATH/res/values/
adlı cihaza
ekleyin:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>
$APPLICATION_PATH/res/values/
için styles.xml
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ı derlemek için $APPLICATION_PATH
öğesine bir BUILD
dosyası ekleyin. Manifest dosyasındaki ${appName}
ve ${mainActivity}
, aşağıda gösterildiği gibi BUILD
politikasında belirtilen dizelerle değiştirilir.
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ı; MainActivity
, kaynak dosyaları ve AndroidManifest.xml
için bağımlılıklar ekler.
android_binary
kuralı, Android cihazınıza yüklemek üzere bir ikili program APK'sı oluşturmak için oluşturulan basic_lib
Android kitaplığını kullanır.
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. Hello World!
metnini içeren bir ekran görünmelidir.
Kamera, CameraX
üzerinden kullanılıyor
Kamera İzinleri
Uygulamamızda kamerayı kullanmak için kullanıcıdan kameraya erişim izni vermesini istememiz gerekir. Kamera izinleri istemek için şunları ekleyin:
AndroidManifest.xml
:
<!-- For using the camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
Aynı dosyada minimum SDK sürümünü 21
, hedef SDK sürümünü ise 27
olarak değiştirin:
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="27" />
Bu, kullanıcıdan kamera izni istemesinin istenmesini ve kamera erişimi için CameraX kitaplığını kullanabilmemizi sağlar.
Kamera izinleri istemek için MediaPipe Framework bileşenleri tarafından sağlanan PermissionHelper
adlı bir yardımcı programı kullanabiliriz. Kullanmak için BUILD
bölgesindeki mediapipe_lib
kuralına "//mediapipe/java/com/google/mediapipe/components:android_components"
bağımlılığı ekleyin.
MainActivity
içinde PermissionHelper
kullanmak için aşağıdaki satırı onCreate
işlevine ekleyin:
PermissionHelper.checkAndRequestCameraPermissions(this);
Bu işlem, kullanıcıdan ekranda bir iletişim kutusuyla birlikte bu uygulamada kamerayı kullanmak için izin istemesini ister.
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ı isteme yanıt verdiğinde MainActivity
devam ettirilir ve onResume()
çağrılır.
Kod, kamerayı kullanma izinlerinin verildiğini onaylar ve ardından kamerayı başlatır.
Uygulamayı yeniden derleyin ve yükleyin. Şimdi uygulama için kameraya erişim isteyen bir istem görmeniz gerekir.
Kamera Erişimi
Kamera izinleri varsa kameradan kare alıp getirebiliriz.
Kareleri kameradan görüntülemek için SurfaceView
kullanacağız. Kameradan gelen her kare bir SurfaceTexture
nesnesinde depolanır. Bunları kullanmak için önce
uygulamamızın düzenini değiştirmemiz gerekir.
$APPLICATION_PATH/res/layout/activity_main.xml
öğesinden TextView
kod bloğunun tamamını kaldırın ve onun yerine aşağıdaki kodu ekleyin:
<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ğunun içinde preview_display_layout
adında yeni bir FrameLayout
ve içinde no_camera_access_preview
adlı bir TextView
bulunuyor. Kamera erişim izinleri verilmediğinde uygulamamız, no_camera_access
değişkeninde depolanan bir dize mesajıyla TextView
değerini gösterir.
$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:
Şimdi SurfaceTexture
ve SurfaceView
nesnelerini MainActivity
öğesine ekleyeceğiz:
private SurfaceTexture previewFrameTexture;
private SurfaceView previewDisplayView;
onCreate(Bundle)
işlevinde, kamera izni istemeden önce aşağıdaki iki satırı ekleyin:
previewDisplayView = new SurfaceView(this);
setupPreviewDisplayView();
Şimdi de setupPreviewDisplayView()
özelliğini 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ımlayıp preview_display_layout
FrameLayout
nesnesine ekleriz. Böylece, bu nesneyi previewFrameTexture
adlı bir SurfaceTexture
nesneyle kamera çerçevelerini görüntülemek için kullanabiliriz.
Kamera çerçevelerini almak üzere previewFrameTexture
kullanmak için CameraX'i kullanacağız.
Çerçeve, CameraX'i kullanmak için CameraXPreviewHelper
adlı bir yardımcı program sağlar.
Bu sınıf, kamera onCameraStarted(@Nullable SurfaceTexture)
üzerinden başlatıldığında dinleyiciyi günceller.
Bu yardımcı programı kullanmak için BUILD
dosyasını değiştirerek "//mediapipe/java/com/google/mediapipe/components:android_camerax_helper"
ürününe bağımlılık ekleyin.
Şimdi CameraXPreviewHelper
dosyasını içe aktarın ve aşağıdaki satırı MainActivity
hedefine ekleyin:
private CameraXPreviewHelper cameraHelper;
Şimdi, 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 nesneye anonim bir işleyici ekler. cameraHelper
, kameranın başladığını sinyalini verdiğinde ve kareleri yakalamak için surfaceTexture
kullanılabilir olduğunda, surfaceTexture
bunu previewFrameTexture
olarak kaydeder ve previewFrameTexture
içindeki kareleri görmeye başlayabilmemiz için previewDisplayView
görünür hale gelir.
Ancak kamerayı başlatmadan önce hangi kamerayı kullanmak istediğimize karar vermemiz gerekiyor. CameraXPreviewHelper
, iki seçenek sunan CameraHelper
öğesinden devralmaktadır: FRONT
ve BACK
. Kararı BUILD
dosyasından meta veri olarak iletebiliriz. Böylece, farklı bir kamera kullanarak uygulamanın başka bir sürümünü oluşturmak için kod değişikliği yapılmasına gerek kalmaz.
Kameradan görüntülediğimiz canlı bir sahnede kenar algılama işlemi gerçekleştirmek için BACK
kamerasını kullanmak istediğimizi varsayarsak meta verileri AndroidManifest.xml
bölümüne ekleyin:
...
<meta-data android:name="cameraFacingFront" android:value="${cameraFacingFront}"/>
</application>
</manifest>
ve helloworld
Android ikili kuralındaki BUILD
öğesinde seçimi manifest_values
öğesinde yeni bir girişle belirtin:
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
uygulamasına bir 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 aşağıdaki satırı startCamera()
işlevinin sonuna ekleyin:
CameraHelper.CameraFacing cameraFacing =
applicationInfo.metaData.getBoolean("cameraFacingFront", false)
? CameraHelper.CameraFacing.FRONT
: CameraHelper.CameraFacing.BACK;
cameraHelper.startCamera(this, cameraFacing, /*unusedSurfaceTexture=*/ null);
Bu noktada, uygulama başarıyla derlenmiş olmalıdır. Ancak uygulamayı cihazınızda çalıştırdığınızda (kamera izinleri verilmiş olsa bile) siyah bir ekran görürsünüz. Bunun nedeni, CameraXPreviewHelper
tarafından sağlanan surfaceTexture
değişkenini kaydetsek bile, previewSurfaceView
öğesinin henüz çıkışını kullanmaması ve ekranda göstermemesidir.
Bir MediaPipe grafiğindeki kareleri kullanmak istediğimizden kamera çıkışını doğrudan bu eğiticide görüntülemek için kod eklemeyeceğiz. Bunun yerine, işlenmek üzere kamera çerçevelerini bir MediaPipe grafiğine nasıl göndereceğimize ve grafiğin çıkışını ekranda nasıl görüntüleyebileceğimize geçiyoruz.
ExternalTextureConverter
kurulumu
SurfaceTexture
, bir akıştaki resim karelerini OpenGL ES dokusu olarak yakalar. MediaPipe grafiği kullanmak için, kameradan çekilen karelerin normal bir Open GL doku nesnesinde depolanması gerekir. Çerçeve, bir SurfaceTexture
nesnesinde depolanan resmi normal bir OpenGL doku nesnesine dönüştürmek için ExternalTextureConverter
adlı bir sınıf sağlar.
ExternalTextureConverter
aracını kullanmak için EglManager
nesnesi tarafından oluşturulan ve yönetilen bir EGLContext
gerekir. EglManager
ve "//mediapipe/java/com/google/mediapipe/glutil"
kullanmak için BUILD
dosyasına bir bağımlılık ekleyin.
MainActivity
içinde aşağıdaki beyanları ekleyin:
private EglManager eglManager;
private ExternalTextureConverter converter;
onCreate(Bundle)
işlevinde, kamera izni istemeden önce eglManager
nesnesini başlatmak için bir ifade ekleyin:
eglManager = new EglManager(null);
Kamera izinlerinin verildiğini onaylamak için MainActivity
öğesinde onResume()
işlevini tanımladığımızı ve startCamera()
işlevini çağırdığımızı hatırlayın. Bu kontrolden önce converter
nesnesini başlatmak için onResume()
öğesine aşağıdaki satırı ekleyin:
converter = new ExternalTextureConverter(eglManager.getContext());
Bu converter
artık eglManager
tarafından yönetilen GLContext
kullanıyor.
Ayrıca, uygulama duraklatılmış duruma geçerse converter
öğesini düzgün bir şekilde kapatabilmemiz için MainActivity
içinde onPause()
işlevini geçersiz kılmamız gerekir:
@Override
protected void onPause() {
super.onPause();
converter.close();
}
previewFrameTexture
çıkışını converter
öğesine bağlamak için aşağıdaki kod bloğunu setupPreviewDisplayView()
öğesine ekleyin:
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, previewDisplayView
öğesine özel bir SurfaceHolder.Callback
ekler ve cihaz ekranındaki kamera çerçevelerinin uygun görüntü boyutunu hesaplamak ve previewFrameTexture
nesnesini bağlayıp hesaplanan displaySize
öğesinin karelerini converter
öğesine göndermek için surfaceChanged(SurfaceHolder holder, int
format, int width, int height)
işlevini uygularız.
Artık kamera çerçevelerini MediaPipe grafiğinde kullanmaya hazırız.
Android'de MediaPipe grafiğini kullanma
Alakalı bağımlılıkları ekleyin
MediaPipe grafiği kullanmak için Android'de MediaPipe çerçevesine bağımlılıklar eklememiz gerekir. İlk olarak MediaPipe çerçevesinin JNI kodunu kullanarak cc_binary
derlemek için bir derleme kuralı ekleyecek ve ardından bu ikili programı uygulamamızda kullanacak bir cc_library
kuralı oluşturacağız. 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ı BUILD
dosyasındaki mediapipe_lib
derleme kuralına ekleyin.
Daha sonra, uygulamada kullanmak istediğimiz MediaPipe grafiğine özgü bağımlılıkları eklememiz gerekir.
İlk olarak, libmediapipe_jni.so
derleme kuralındaki tüm hesap makinesi kodlarına bağımlılık ekleyin:
"//mediapipe/graphs/edge_detection:mobile_calculators",
MediaPipe grafikleri .pbtxt
dosyalarıdır ancak bunları uygulamada kullanmak için .binarypb
dosyası oluşturmak üzere mediapipe_binary_graph
derleme kuralını kullanmamız gerekir.
helloworld
Android ikili derleme kuralında, grafiğe özgü mediapipe_binary_graph
hedefini öğe olarak ekleyin:
assets = [
"//mediapipe/graphs/edge_detection:mobile_gpu_binary_graph",
],
assets_dir = "",
assets
derleme kuralında, grafiğinizde kullanılan TensorFlowLite modelleri gibi başka öğeler de ekleyebilirsiniz.
Buna ek olarak, grafiğe özel özellikler için daha sonra MainActivity
içinde alınacak ek manifest_values
ekleyin:
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
değerinin, ikili grafiğin dosya adını gösterdiğini unutmayın. Bu, mediapipe_binary_graph
hedefindeki output_name
alanı tarafından belirlenir.
inputVideoStreamName
ve outputVideoStreamName
, grafikte belirtilen giriş ve çıkış video akışı adıdır.
Şimdi MainActivity
cihazının MediaPipe çerçevesini yüklemesi gerekir. Ayrıca, çerçeve OpenCV'yi kullandığından MainActvity
, OpenCV
dosyasını da yüklemelidir. Her iki bağımlılığı da yüklemek için MainActivity
içinde (sınıfın içinde ancak herhangi bir işlevin içinde değil) aşağıdaki kodu kullanın:
static {
// Load all native libraries needed by the app.
System.loadLibrary("mediapipe_jni");
System.loadLibrary("opencv_java3");
}
Grafiği MainActivity
aracında kullanın
Öncelikle, grafiğin .pbtxt
dosyasından derlenen .binarypb
öğesini içeren öğeyi yüklememiz gerekir. Bunu yapmak için bir MediaPipe yardımcı programı
(AndroidAssetUtil
) kullanabiliriz.
eglManager
öğesini başlatmadan önce onCreate(Bundle)
içinde öğe yöneticisini ilk kullanıma hazırlayın:
// Initialize asset manager so that MediaPipe native libraries can access the app assets, e.g.,
// binary graphs.
AndroidAssetUtil.initializeNativeAssetManager(this);
Şimdi, converter
tarafından hazırlanan kamera çerçevelerini MediaPipe grafiğine gönderen ve grafiği çalıştıran, çıkışı hazırlayan ve daha sonra, çıktıyı görüntülemek için previewDisplayView
öğesini güncelleyen bir FrameProcessor
nesnesi oluşturmamız gerekiyor. FrameProcessor
özelliğini bildirmek için aşağıdaki kodu ekleyin:
private FrameProcessor processor;
ve eglManager
uygulamasını başlattı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
, işleme için converter
öğesinden dönüştürülen kareleri kullanmalıdır. converter
başlatıldıktan sonra aşağıdaki satırı onResume()
öğesine ekleyin:
converter.setConsumer(processor);
processor
, çıkışını previewDisplayView
adresine göndermelidir. Bunu yapmak için aşağıdaki işlev tanımlarını özel SurfaceHolder.Callback
aracımıza ekleyin:
@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, processor
öğesinin VideoSurfaceOutput
ile Surface
arasındaki kısmı vardı. İmha edildiğinde processor
VideoSurfaceOutput
hükümlerinden kaldırırız.
Hepsi bu kadar! Artık uygulamayı cihazda başarıyla derleyip çalıştırabilir ve canlı kamera feed'inde Sobel kenar algılamanın çalıştığını görebilirsiniz. Tebrikler!
Herhangi bir sorunla karşılaşırsanız lütfen eğitimin tam koduna buradan ulaşabilirsiniz.