परिचय
नमस्ते दुनिया! ट्यूटोरियल MediaPipe Framework का इस्तेमाल करके, ऐसा Android ऐप्लिकेशन डेवलप करता है जो Android पर MediaPipe ग्राफ़ चलाता है.
आपको क्या बनाना होगा
लाइव वीडियो में, रीयल-टाइम में सोबेल एज डिटेक्शन करने के लिए एक आसान कैमरा ऐप्लिकेशन किसी Android डिवाइस पर स्ट्रीम करना है.
सेटअप
- अपने सिस्टम पर MediaPipe Framework इंस्टॉल करें, फ़्रेमवर्क इंस्टॉलेशन देखें गाइड पढ़ें.
- Android डेवलपमेंट SDK टूल और Android NDK इंस्टॉल करें. इसका तरीका जानें [फ़्रेमवर्क इंस्टॉलेशन गाइड].
- अपने Android डिवाइस पर डेवलपर के लिए सेटिंग और टूल चालू करें.
- Android ऐप्लिकेशन बनाने और डिप्लॉय करने के लिए, अपने सिस्टम पर Bazu सेट अप करें.
किनारे का पता लगाने के लिए ग्राफ़
हम इस ग्राफ़ का इस्तेमाल करेंगे, 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"
}
ग्राफ़ का विज़ुअलाइज़ेशन नीचे दिखाया गया है:
इस ग्राफ़ में, आने वाले सभी फ़्रेम के लिए input_video
नाम की एक इनपुट स्ट्रीम मौजूद है
जिसे आपके डिवाइस के कैमरे से मिलेगा.
ग्राफ़ के पहले नोड, LuminanceCalculator
, में एक पैकेट (इमेज) होता है
फ़्रेम) के आकार के साथ दिखाया जाता है और OpenGL शेडर का इस्तेमाल करके ल्यूमिनेंस में बदलाव लागू करता है. नतीजे के तौर पर मिला नतीजा
इमेज फ़्रेम को luma_video
आउटपुट स्ट्रीम पर भेजा जाता है.
दूसरा नोड, SobelEdgesCalculator
किनारे की पहचान करने की सुविधा को इनकमिंग पर लागू करता है
luma_video
स्ट्रीम में पैकेट और आउटपुट के नतीजे में output_video
आउटपुट मिलता है
स्ट्रीम.
हमारा Android ऐप्लिकेशन इस
output_video
स्ट्रीम.
शुरुआती कम से कम ऐप्लिकेशन सेटअप
हम पहले एक आसान Android ऐप्लिकेशन से शुरुआत करते हैं, जो "हैलो वर्ल्ड!"
स्क्रीन पर. अगर आपको Android डिवाइस बनाने की जानकारी है, तो इस चरण को छोड़ा जा सकता है
bazel
का इस्तेमाल करने वाले ऐप्लिकेशन.
नई डायरेक्ट्री बनाएं, जहां आप अपना Android ऐप्लिकेशन बनाएंगे. इसके लिए
उदाहरण के लिए, इस ट्यूटोरियल का पूरा कोड यहां देखें:
mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic
. हम करेंगे
पूरे कोडलैब में इस पाथ को $APPLICATION_PATH
के तौर पर दिखाएं.
ध्यान दें कि ऐप्लिकेशन के पाथ में:
- ऐप्लिकेशन का नाम
helloworld
है. - ऐप्लिकेशन का
$PACKAGE_PATH
com.google.mediapipe.apps.basic
है. इस ट्यूटोरियल में कोड स्निपेट में इसका इस्तेमाल किया गया है. इसलिए, कृपया कोड स्निपेट को कॉपी/इस्तेमाल करने पर, आपका अपना$PACKAGE_PATH
.
activity_main.xml
फ़ाइल को $APPLICATION_PATH/res/layout
में जोड़ें. यह दिखाता है
Hello
World!
स्ट्रिंग वाले ऐप्लिकेशन की फ़ुल स्क्रीन पर 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
में कोई आसान MainActivity.java
जोड़ें, ताकि कॉन्टेंट लोड हो सके
activity_main.xml
लेआउट का इस्तेमाल कर सकते हैं, जैसा कि नीचे दिखाया गया है:
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);
}
}
AndroidManifest.xml
को $APPLICATION_PATH
में एक मेनिफ़ेस्ट फ़ाइल जोड़ें, जिसमें
आवेदन शुरू होने पर MainActivity
को लॉन्च किया जाएगा:
<?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>
हम अपने ऐप्लिकेशन में Theme.AppCompat
थीम का इस्तेमाल कर रहे हैं, इसलिए हमें इन ऐप्लिकेशन की ज़रूरत है
में सही संदर्भ शामिल करें. colors.xml
को इसमें जोड़ें
$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>
$APPLICATION_PATH/res/values/
में styles.xml
जोड़ें:
<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>
ऐप्लिकेशन बनाने के लिए, $APPLICATION_PATH
में BUILD
फ़ाइल जोड़ें, और
मेनिफ़ेस्ट में ${appName}
और ${mainActivity}
को स्ट्रिंग से बदल दिया जाएगा
जैसा कि नीचे दिखाया गया है, BUILD
में बताया गया है.
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
नियम, रिसॉर्स फ़ाइलों और MainActivity
के लिए डिपेंडेंसी जोड़ता है
और AndroidManifest.xml
.
android_binary
नियम, इसके लिए जनरेट की गई basic_lib
Android लाइब्रेरी का इस्तेमाल करता है
अपने Android डिवाइस पर इंस्टॉल करने के लिए, बाइनरी APK बनाएं.
ऐप्लिकेशन बनाने के लिए, नीचे दिए गए निर्देश का इस्तेमाल करें:
bazel build -c opt --config=android_arm64 $APPLICATION_PATH:helloworld
adb install
का इस्तेमाल करके जनरेट की गई APK फ़ाइल इंस्टॉल करें. उदाहरण के लिए:
adb install bazel-bin/$APPLICATION_PATH/helloworld.apk
अपने डिवाइस पर ऐप्लिकेशन खोलें. इस इमेज में टेक्स्ट के साथ स्क्रीन दिखनी चाहिए
Hello World!
.
CameraX
के ज़रिए कैमरे का इस्तेमाल किया जा रहा है
कैमरे के लिए अनुमतियां
हमारे ऐप्लिकेशन में कैमरे का इस्तेमाल करने के लिए, हमें उपयोगकर्ता से अनुरोध करना होगा कि वह
कैमरे को ऐक्सेस करने की अनुमति दें. कैमरा ऐक्सेस करने की अनुमतियों का अनुरोध करने के लिए, इन्हें जोड़ें
AndroidManifest.xml
:
<!-- For using the camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
इसमें, SDK टूल के कम से कम वर्शन को 21
और टारगेट SDK वर्शन को 27
में बदलें.
एक ही फ़ाइल:
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="27" />
इससे यह पक्का होता है कि उपयोगकर्ता को कैमरा ऐक्सेस करने की अनुमति मांगने का अनुरोध किया जाएगा. इसके बाद, यह सुविधा चालू हो जाएगी हमें कैमरा ऐक्सेस करने के लिए CameraX लाइब्रेरी इस्तेमाल करनी है.
कैमरा ऐक्सेस करने की अनुमतियों का अनुरोध करने के लिए, हम MediaPipe Framework के ज़रिए उपलब्ध कराई गई सुविधा का इस्तेमाल कर सकते हैं
कॉम्पोनेंट, जैसे कि PermissionHelper
. इसका इस्तेमाल करने के लिए, कोई डिपेंडेंसी जोड़ें
"//mediapipe/java/com/google/mediapipe/components:android_components"
BUILD
में mediapipe_lib
नियम.
MainActivity
में PermissionHelper
का इस्तेमाल करने के लिए, नीचे दी गई लाइन को
onCreate
फ़ंक्शन:
PermissionHelper.checkAndRequestCameraPermissions(this);
यह उपयोगकर्ता को स्क्रीन पर एक डायलॉग दिखाकर, इसकी अनुमतियों का अनुरोध करने के लिए कहता है इस ऐप्लिकेशन के कैमरे का इस्तेमाल करें.
उपयोगकर्ता के जवाब को मैनेज करने के लिए, यह कोड जोड़ें:
@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()
तरीके को खाली छोड़ देंगे. जब उपयोगकर्ता जवाब देता है
प्रॉम्प्ट से, MainActivity
फिर से शुरू हो जाएगा और onResume()
को कॉल किया जाएगा.
कोड से यह पुष्टि की जाएगी कि कैमरा इस्तेमाल करने की अनुमतियां दे दी गई हैं,
और कैमरा चालू हो जाएगा.
ऐप्लिकेशन फिर से बनाएं और इंस्टॉल करें. इसके बाद, आपको ऐप्लिकेशन के लिए कैमरे की ऐक्सेस.
कैमरे का ऐक्सेस
कैमरे की अनुमतियां उपलब्ध होने पर, हम कैमरा.
कैमरे से फ़्रेम देखने के लिए, हम SurfaceView
का इस्तेमाल करेंगे. हर फ़्रेम
को SurfaceTexture
ऑब्जेक्ट में सेव किया जाएगा. इनका इस्तेमाल करने के लिए, हम
पहले हमारे ऐप्लिकेशन का लेआउट बदलना होगा.
यहां से पूरा TextView
कोड ब्लॉक हटाएं
$APPLICATION_PATH/res/layout/activity_main.xml
और यह कोड जोड़ें
इसके बजाय:
<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>
इस कोड ब्लॉक में preview_display_layout
नाम का एक नया FrameLayout
और
TextView
इसके अंदर नेस्ट किया गया है, जिसका नाम no_camera_access_preview
है. जब कैमरा
ऐक्सेस की अनुमतियां नहीं दी गई हैं, तो हमारा ऐप्लिकेशन
स्ट्रिंग मैसेज के साथ TextView
, जिसे no_camera_access
वैरिएबल में सेव किया गया है.
$APPLICATION_PATH/res/values/strings.xml
फ़ाइल में यह लाइन जोड़ें:
<string name="no_camera_access" translatable="false">Please grant camera permissions.</string>
जब उपयोगकर्ता कैमरा ऐक्सेस करने की अनुमति नहीं देता है, तो स्क्रीन अब ऐसी दिखेगी शामिल करें:
अब हम SurfaceTexture
और SurfaceView
ऑब्जेक्ट को
MainActivity
:
private SurfaceTexture previewFrameTexture;
private SurfaceView previewDisplayView;
onCreate(Bundle)
फ़ंक्शन में, नीचे दी गई दो पंक्तियां पहले जोड़ें
कैमरे की अनुमतियों के लिए अनुरोध कर रहा है:
previewDisplayView = new SurfaceView(this);
setupPreviewDisplayView();
और अब setupPreviewDisplayView()
को परिभाषित करने वाला कोड जोड़ें:
private void setupPreviewDisplayView() {
previewDisplayView.setVisibility(View.GONE);
ViewGroup viewGroup = findViewById(R.id.preview_display_layout);
viewGroup.addView(previewDisplayView);
}
हम एक नया SurfaceView
ऑब्जेक्ट तय करते हैं और उसे
preview_display_layout
FrameLayout
ऑब्जेक्ट ताकि हम उसे दिखाने के लिए उसका इस्तेमाल कर सकें
previewFrameTexture
नाम के SurfaceTexture
ऑब्जेक्ट का इस्तेमाल करके, कैमरे के फ़्रेम ऐक्सेस किए जा सकते हैं.
कैमरे के फ़्रेम पाने के लिए previewFrameTexture
का इस्तेमाल करने के लिए, हम CameraX इस्तेमाल करेंगे.
फ़्रेमवर्क, CameraX का इस्तेमाल करने के लिए CameraXPreviewHelper
नाम की यूटिलिटी उपलब्ध कराता है.
जब कैमरा चालू किया जाता है, तब यह क्लास लिसनर को अपडेट करती है
onCameraStarted(@Nullable SurfaceTexture)
.
इस सुविधा का इस्तेमाल करने के लिए, BUILD
फ़ाइल में बदलाव करें, ताकि इस पर निर्भरता जोड़ी जा सके
"//mediapipe/java/com/google/mediapipe/components:android_camerax_helper"
.
अब CameraXPreviewHelper
को इंपोर्ट करें और नीचे दी गई लाइन को इसमें जोड़ें
MainActivity
:
private CameraXPreviewHelper cameraHelper;
अब हम लागू करने की प्रोसेस को startCamera()
में जोड़ सकते हैं:
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);
});
}
इससे एक नया CameraXPreviewHelper
ऑब्जेक्ट बन जाएगा और उसमें पहचान छिपाई गई
लिसनर है. जब cameraHelper
को पता चलता है कि कैमरा चालू हो गया है
फ़्रेम हासिल करने के लिए एक surfaceTexture
उपलब्ध है, हम समय बचाते हैं
previewFrameTexture
के तौर पर surfaceTexture
और previewDisplayView
बनाएं
ताकि हमें previewFrameTexture
से फ़्रेम दिखने लगें.
हालांकि, कैमरा शुरू करने से पहले, हमें यह तय करना होगा कि हमें कौनसा कैमरा इस्तेमाल करना है
इस्तेमाल करें. CameraXPreviewHelper
को CameraHelper
से इनहेरिट किया जाता है, जो दो नतीजे देते हैं
विकल्प, FRONT
और BACK
. हम BUILD
फ़ाइल से फ़ैसला ले सकते हैं
जैसे कि मेटाडेटा का दूसरा वर्शन बनाने के लिए किसी कोड में बदलाव की ज़रूरत नहीं होगी
ऐप पर जाएं.
मान लीजिए कि हमें लाइव सीन के किनारे का पता लगाने के लिए, BACK
कैमरा का इस्तेमाल करना है
जिन्हें हम कैमरे से देखते हैं तो मेटाडेटा को AndroidManifest.xml
में जोड़ें:
...
<meta-data android:name="cameraFacingFront" android:value="${cameraFacingFront}"/>
</application>
</manifest>
और helloworld
Android बाइनरी नियम में BUILD
में चुने गए विकल्प को तय करें
manifest_values
में एक नई प्रविष्टि के साथ:
manifest_values = {
"applicationId": "com.google.mediapipe.apps.basic",
"appName": "Hello World",
"mainActivity": ".MainActivity",
"cameraFacingFront": "False",
},
अब manifest_values
में दिए गए मेटाडेटा को वापस पाने के लिए, MainActivity
में,
कोई ApplicationInfo
ऑब्जेक्ट जोड़ें:
private ApplicationInfo applicationInfo;
onCreate()
फ़ंक्शन में, यह जोड़ें:
try {
applicationInfo =
getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
Log.e(TAG, "Cannot find application info: " + e);
}
अब startCamera()
फ़ंक्शन के आखिर में नीचे दी गई लाइन जोड़ें:
CameraHelper.CameraFacing cameraFacing =
applicationInfo.metaData.getBoolean("cameraFacingFront", false)
? CameraHelper.CameraFacing.FRONT
: CameraHelper.CameraFacing.BACK;
cameraHelper.startCamera(this, cameraFacing, /*unusedSurfaceTexture=*/ null);
इस समय, ऐप्लिकेशन सफलतापूर्वक बन जाना चाहिए. हालांकि, जब आप दौड़ते हैं,
तो आपको एक काली स्क्रीन (भले ही कैमरा)
अनुमतियां दी गई हैं). ऐसा इसलिए होता है, क्योंकि भले ही हम
CameraXPreviewHelper
से मिला surfaceTexture
वैरिएबल,
previewSurfaceView
, आउटपुट का इस्तेमाल नहीं करता और उसे स्क्रीन पर दिखाता है.
हम MediaPipe ग्राफ़ में फ़्रेम का इस्तेमाल करना चाहते हैं, इसलिए हम इस ट्यूटोरियल में कैमरा आउटपुट देखें. इसके बजाय, हम यह देखते हैं कि हम MediaPipe ग्राफ़ पर प्रोसेस करने के लिए कैमरा फ़्रेम भेज सकते हैं. साथ ही, स्क्रीन पर ग्राफ़ का आउटपुट.
ExternalTextureConverter
सेटअप
SurfaceTexture
किसी स्ट्रीम से OpenGL ES के तौर पर इमेज फ़्रेम कैप्चर करता है
बनावट. MediaPipe ग्राफ़ का इस्तेमाल करने के लिए, कैमरे से कैप्चर किए गए फ़्रेम ऐसे होने चाहिए:
को किसी सामान्य Open GL टेक्सचर ऑब्जेक्ट में सेव किया जाता है. यह फ़्रेमवर्क एक क्लास,
SurfaceTexture
में सेव की गई इमेज को बदलने के लिए ExternalTextureConverter
ऑब्जेक्ट को सामान्य OpenGL टेक्स्चर ऑब्जेक्ट पर ले जाता है.
ExternalTextureConverter
का इस्तेमाल करने के लिए, हमें EGLContext
की भी ज़रूरत होगी, जो
EglManager
ऑब्जेक्ट से बनाया और मैनेज किया जाता है. BUILD
पर डिपेंडेंसी जोड़ें
EglManager
, "//mediapipe/java/com/google/mediapipe/glutil"
इस्तेमाल करने के लिए फ़ाइल.
MainActivity
में, यह एलान जोड़ें:
private EglManager eglManager;
private ExternalTextureConverter converter;
onCreate(Bundle)
फ़ंक्शन में, शुरू करने के लिए कोई स्टेटमेंट जोड़ें
कैमरे की अनुमतियों का अनुरोध करने से पहले, eglManager
ऑब्जेक्ट:
eglManager = new EglManager(null);
याद रखें कि हमने MainActivity
में onResume()
फ़ंक्शन तय किया था, ताकि इसकी पुष्टि की जा सके
कैमरे के इस्तेमाल की अनुमतियां दे दी गई हैं. आपने startCamera()
को कॉल किया. इससे पहले
सही का निशान लगाएं. converter
शुरू करने के लिए, onResume()
में इस लाइन को जोड़ें
ऑब्जेक्ट:
converter = new ExternalTextureConverter(eglManager.getContext());
अब यह converter
, GLContext
का इस्तेमाल करता है, जिसे eglManager
मैनेज करता है.
हमें MainActivity
में onPause()
फ़ंक्शन को भी बदलना होगा, ताकि
अगर ऐप्लिकेशन रुका हुआ है, तो हम converter
को ठीक से बंद कर देते हैं:
@Override
protected void onPause() {
super.onPause();
converter.close();
}
previewFrameTexture
के आउटपुट को converter
से जोड़ने के लिए, जोड़ें
setupPreviewDisplayView()
पर कोड का निम्न ब्लॉक:
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) {}
});
इस कोड ब्लॉक में, हम एक कस्टम SurfaceHolder.Callback
जोड़ते हैं
सही डिसप्ले साइज़ की गणना करने के लिए, previewDisplayView
और surfaceChanged(SurfaceHolder holder, int
format, int width, int height)
फ़ंक्शन लागू करें
कैमरा फ़्रेम को सेट करने और previewFrameTexture
को जोड़ने के लिए
ऑब्जेक्ट सबमिट करें और परिकलित displaySize
के फ़्रेम converter
पर भेजें.
अब हम MediaPipe ग्राफ़ में कैमरा फ़्रेम का इस्तेमाल करने के लिए तैयार हैं.
Android में MediaPipe ग्राफ़ का इस्तेमाल करना
काम की डिपेंडेंसी जोड़ें
MediaPipe ग्राफ़ का इस्तेमाल करने के लिए, हमें MediaPipe फ़्रेमवर्क में डिपेंडेंसी जोड़नी होगी
Android पर देखें. हम सबसे पहले जेएनआई कोड का इस्तेमाल करके cc_binary
बनाने के लिए बिल्ड नियम जोड़ेंगे
और फिर इस बाइनरी का इस्तेमाल करने के लिए cc_library
नियम बनाएं
हमारे ऐप्लिकेशन में. अपनी BUILD
फ़ाइल में यह कोड ब्लॉक जोड़ें:
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_lib
बिल्ड नियम में डिपेंडेंसी ":mediapipe_jni_lib"
जोड़ें
BUILD
फ़ाइल.
इसके बाद, आपको जिस MediaPipe ग्राफ़ का इस्तेमाल करना है उसकी डिपेंडेंसी जोड़नी होगी ऐप्लिकेशन में.
सबसे पहले, libmediapipe_jni.so
में मौजूद सभी कैलकुलेटर कोड पर डिपेंडेंसी जोड़ें
बिल्ड नियम:
"//mediapipe/graphs/edge_detection:mobile_calculators",
MediaPipe ग्राफ़ .pbtxt
फ़ाइलें हैं, लेकिन ऐप्लिकेशन में उनका उपयोग करने के लिए हमें
ताकि .binarypb
फ़ाइल जनरेट करने के लिए mediapipe_binary_graph
बिल्ड नियम का इस्तेमाल किया जा सके.
helloworld
Android बाइनरी बिल्ड के नियम में, mediapipe_binary_graph
जोड़ें
एक एसेट के रूप में ग्राफ़ से संबंधित लक्ष्य:
assets = [
"//mediapipe/graphs/edge_detection:mobile_gpu_binary_graph",
],
assets_dir = "",
assets
बिल्ड के नियम में, TensorFlowLite जैसी अन्य ऐसेट भी जोड़ी जा सकती हैं
मॉडल का इस्तेमाल करें.
इसके अलावा, यहां बताई गई प्रॉपर्टी के लिए अतिरिक्त manifest_values
जोड़ें
ग्राफ़, जिसे बाद में MainActivity
में वापस लिया जाएगा:
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
, बाइनरी ग्राफ़ का फ़ाइल नाम दिखाता है,
mediapipe_binary_graph
टारगेट में output_name
फ़ील्ड से तय होती है.
inputVideoStreamName
और outputVideoStreamName
इनपुट और आउटपुट हैं
वीडियो स्ट्रीम का नाम, जो ग्राफ़ में दिया गया है.
अब MainActivity
को MediaPipe फ़्रेमवर्क को लोड करना होगा. साथ ही,
फ़्रेमवर्क, OpenCV का इस्तेमाल करता है. इसलिए, MainActvity
को भी OpenCV
लोड करना चाहिए. इसका इस्तेमाल करें
MainActivity
में निम्न कोड (क्लास के अंदर, लेकिन किसी भी फ़ंक्शन के अंदर नहीं)
दोनों डिपेंडेंसी लोड करने के लिए:
static {
// Load all native libraries needed by the app.
System.loadLibrary("mediapipe_jni");
System.loadLibrary("opencv_java3");
}
MainActivity
में ग्राफ़ का इस्तेमाल करें
सबसे पहले, हमें उस ऐसेट को लोड करना होगा जिसमें इनसे इकट्ठा किया गया .binarypb
शामिल है
ग्राफ़ की .pbtxt
फ़ाइल. ऐसा करने के लिए, हम MediaPipe उपयोगिता का उपयोग कर सकते हैं,
AndroidAssetUtil
.
शुरू करने से पहले, onCreate(Bundle)
में ऐसेट मैनेजर को शुरू करें
eglManager
:
// Initialize asset manager so that MediaPipe native libraries can access the app assets, e.g.,
// binary graphs.
AndroidAssetUtil.initializeNativeAssetManager(this);
अब हमें एक ऐसा FrameProcessor
ऑब्जेक्ट सेट अप करना होगा जो कैमरे के फ़्रेम भेज सके
को converter
के ज़रिए MediaPipe ग्राफ़ के लिए तैयार किया जाता है और ग्राफ़ को चलाया जाता है,
आउटपुट, और फिर आउटपुट दिखाने के लिए previewDisplayView
को अपडेट करता है. जोड़ें
FrameProcessor
का एलान करने के लिए यह कोड दिया गया है:
private FrameProcessor processor;
और eglManager
को शुरू करने के बाद, इसे onCreate(Bundle)
में शुरू करें:
processor =
new FrameProcessor(
this,
eglManager.getNativeContext(),
applicationInfo.metaData.getString("binaryGraphName"),
applicationInfo.metaData.getString("inputVideoStreamName"),
applicationInfo.metaData.getString("outputVideoStreamName"));
processor
को converter
से बदले गए फ़्रेम का इस्तेमाल करना होगा
प्रोसेस चल रही है. शुरू करने के बाद, नीचे दी गई लाइन को onResume()
में जोड़ें
converter
:
converter.setConsumer(processor);
processor
को अपना आउटपुट previewDisplayView
को भेजना चाहिए. ऐसा करने के लिए, जोड़ें
नीचे दी गई फ़ंक्शन की परिभाषाएं, हमारे कस्टम SurfaceHolder.Callback
में दी गई हैं:
@Override
public void surfaceCreated(SurfaceHolder holder) {
processor.getVideoSurfaceOutput().setSurface(holder.getSurface());
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
processor.getVideoSurfaceOutput().setSurface(null);
}
SurfaceHolder
बनाने पर, हमने Surface
को
processor
में से VideoSurfaceOutput
. इसे खत्म कर दिए जाने पर, हम इसे यहां से हटा देते हैं
processor
के VideoSurfaceOutput
.
यह बहुत आसान है! अब आप इसे बनाने और चलाने में सक्षम होना चाहिए डिवाइस में मौजूद ऐप्लिकेशन को लॉक किया गया है और सॉबेल एज डिटेक्शन को लाइव कैमरे में चलते हुए देखा गया है फ़ीड! बधाई हो!
अगर आपको कोई समस्या हुई है, तो कृपया ट्यूटोरियल का पूरा कोड देखें यहां पढ़ें.