برای فراخوانی Google Cloud API از برنامهتان، باید یک REST API واسطه ایجاد کنید که مجوزدهی را مدیریت کند و از مقادیر محرمانه مانند کلیدهای API محافظت کند. سپس باید در برنامه تلفن همراهتان کدی بنویسید تا با این سرویس واسطه اصالتسنجی و ارتباط برقرار کند.
یکی از راههای ایجاد این REST API استفاده از Firebase Authentication و Functions است که به شما یک درگاه مدیریتشده و بدون سرور به Google Cloud APIs میدهد که اصالتسنجی را مدیریت میکند و میتواند از برنامه تلفن همراه شما با کیتهای توسعه نرمافزار ازپیشساختهشده فراخوانی شود.
این راهنما نشان میدهد که چگونه از این تکنیک برای فراخوانی Cloud Vision API از برنامهتان استفاده کنید. این روش به همه کاربران اصالتسنجیشده اجازه میدهد تا ازطریق پروژه Cloud شما به سرویسهای صورتحساب Cloud Vision دسترسی داشته باشند، بنابراین قبلاز ادامه، درنظر بگیرید که آیا این سازوکار اصالتسنجی برای مورد استفاده شما کافی است یا نه.
قبل از شروع
پیکربندی پروژه
- اگر قبلاً این کار را نکردهاید، Firebase را به پروژه Android خود اضافه کنید.
-
اگر قبلاً میاناهای برنامهسازی کاربردی ابری را برای پروژهتان فعال نکردهاید، اکنون این کار را انجام دهید:
- Firebase ML صفحه API را در Firebase کنسول باز کنید.
-
اگر قبلاً پروژهتان را به طرح قیمتگذاری Blaze پرداخت به اندازه استفاده ارتقا ندادهاید، روی ارتقا دادن کلیک کنید تا این کار را انجام دهید. (فقط درصورتی از شما خواسته میشود ارتقا دهید که پروژهتان در طرح قیمتگذاری Blaze نباشد.)
فقط پروژههایی که در طرح قیمتگذاری Blaze هستند میتوانند از میاناهای برنامهسازی کاربردی مبتنی بر Cloud استفاده کنند.
- اگر میاناهای برنامهسازی کاربردی مبتنی بر Cloud ازقبل فعال نشدهاند، روی فعال کردن میاناهای برنامهسازی کاربردی مبتنی بر Cloud کلیک کنید.
- کلیدهای Firebase API موجودتان را پیکربندی کنید تا دسترسی به Cloud Vision API را غیرمجاز کنید:
- صفحه اعتبارنامهها را در کنسول Cloud باز کنید.
- برای هر کلید میانای برنامهسازی کاربردی در فهرست، نمای ویرایش را باز کنید و در بخش «محدودیتهای کلید»، همه میاناهای برنامهسازی کاربردی دردسترس را بهجز میانای برنامهسازی کاربردی Cloud Vision به فهرست اضافه کنید.
استقرار تابع قابلفراخوانی
سپس، Cloud Function را که برای پل زدن بین برنامه و Cloud Vision API استفاده خواهید کرد مستقر کنید. مخزن functions-samples حاوی نمونهای است که میتوانید از آن استفاده کنید.
بهطور پیشفرض، دسترسی به Cloud Vision API ازطریق این تابع فقط به کاربران اصالتسنجیشده برنامهتان اجازه میدهد به Cloud Vision API دسترسی داشته باشند. میتوانید تابع را برای الزامات مختلف اصلاح کنید.
برای استقرار تابع:
- مخزن functions-samples را شبیهسازی یا بارگیری کنید
و به دایرکتوری
Node-1st-gen/vision-annotate-imageبروید:git clone https://github.com/firebase/functions-samplescd Node-1st-gen/vision-annotate-image - نصب وابستگیها:
cd functionsnpm installcd .. - اگر Firebase CLI را ندارید، آن را نصب کنید.
- پروژه Firebase را در فهرست راهنمای
vision-annotate-imageمقداردهی اولیه کنید. وقتی درخواست شد، پروژهتان را در فهرست انتخاب کنید.firebase init
- تابع را مستقر کنید:
firebase deploy --only functions:annotateImage
افزودن Firebase Auth به برنامه
تابع قابلفراخوانی که در بالا مستقر شده است، هر درخواستی را از کاربران غیرمعتبر برنامهتان رد خواهد کرد. اگر قبلاً این کار را نکردهاید، باید Firebase Auth را به برنامهتان اضافه کنید.
افزودن وابستگیهای لازم به برنامه
<project>/<app-module>/build.gradle.kts یا <project>/<app-module>/build.gradle) اضافه کنید:
implementation("com.google.firebase:firebase-functions:23.0.0") implementation("com.google.code.gson:gson:2.8.6")
اکنون آماده برچسبگذاری تصاویر هستید.
۱. آماده کردن تصویر ورودی
برای فراخوانی Cloud Vision، تصویر باید بهصورت رشته کدبندیشده با base64 قالببندی شود. برای پردازش تصویر از URI فایل ذخیرهشده:- تصویر را بهعنوان شیء
Bitmapدریافت کنید:Kotlin
var bitmap: Bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)
Java
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
- درصورت تمایل، تصویر را کوچک کنید تا در پهنای باند صرفهجویی شود.
اندازههای تصویر توصیهشده Cloud Vision را ببینید.
Kotlin
private fun scaleBitmapDown(bitmap: Bitmap, maxDimension: Int): Bitmap { val originalWidth = bitmap.width val originalHeight = bitmap.height var resizedWidth = maxDimension var resizedHeight = maxDimension if (originalHeight > originalWidth) { resizedHeight = maxDimension resizedWidth = (resizedHeight * originalWidth.toFloat() / originalHeight.toFloat()).toInt() } else if (originalWidth > originalHeight) { resizedWidth = maxDimension resizedHeight = (resizedWidth * originalHeight.toFloat() / originalWidth.toFloat()).toInt() } else if (originalHeight == originalWidth) { resizedHeight = maxDimension resizedWidth = maxDimension } return Bitmap.createScaledBitmap(bitmap, resizedWidth, resizedHeight, false) }
Java
private Bitmap scaleBitmapDown(Bitmap bitmap, int maxDimension) { int originalWidth = bitmap.getWidth(); int originalHeight = bitmap.getHeight(); int resizedWidth = maxDimension; int resizedHeight = maxDimension; if (originalHeight > originalWidth) { resizedHeight = maxDimension; resizedWidth = (int) (resizedHeight * (float) originalWidth / (float) originalHeight); } else if (originalWidth > originalHeight) { resizedWidth = maxDimension; resizedHeight = (int) (resizedWidth * (float) originalHeight / (float) originalWidth); } else if (originalHeight == originalWidth) { resizedHeight = maxDimension; resizedWidth = maxDimension; } return Bitmap.createScaledBitmap(bitmap, resizedWidth, resizedHeight, false); }
Kotlin
// Scale down bitmap size bitmap = scaleBitmapDown(bitmap, 640)
Java
// Scale down bitmap size bitmap = scaleBitmapDown(bitmap, 640);
- شیء نگاشت بیتی را به رشته کدبندیشده base64 تبدیل کنید:
Kotlin
// Convert bitmap to base64 encoded string val byteArrayOutputStream = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream) val imageBytes: ByteArray = byteArrayOutputStream.toByteArray() val base64encoded = Base64.encodeToString(imageBytes, Base64.NO_WRAP)
Java
// Convert bitmap to base64 encoded string ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); byte[] imageBytes = byteArrayOutputStream.toByteArray(); String base64encoded = Base64.encodeToString(imageBytes, Base64.NO_WRAP);
تصویر نشاندادهشده توسط شیء
Bitmap باید
عمودی باشد و به چرخش اضافی نیاز نداشته باشد.
۲. فراخوانی تابع قابلفراخوانی برای برچسبگذاری تصویر
برای برچسبگذاری اشیاء در تصویر، تابع قابلفراخوانی را با ارسال درخواست JSON Cloud Vision فراخوانی کنید.ابتدا، نمونهای از Cloud Functions را مقداردهی اولیه کنید:
Kotlin
private lateinit var functions: FirebaseFunctions // ... functions = Firebase.functionsJava
private FirebaseFunctions mFunctions; // ... mFunctions = FirebaseFunctions.getInstance();روشی برای فراخوانی تابع تعریف کنید:
Kotlin
private fun annotateImage(requestJson: String): Task<JsonElement> { return functions .getHttpsCallable("annotateImage") .call(requestJson) .continueWith { task -> // This continuation runs on either success or failure, but if the task // has failed then result will throw an Exception which will be // propagated down. val result = task.result?.data JsonParser.parseString(Gson().toJson(result)) } }Java
private Task<JsonElement> annotateImage(String requestJson) { return mFunctions .getHttpsCallable("annotateImage") .call(requestJson) .continueWith(new Continuation<HttpsCallableResult, JsonElement>() { @Override public JsonElement then(@NonNull Task<HttpsCallableResult> task) { // This continuation runs on either success or failure, but if the task // has failed then getResult() will throw an Exception which will be // propagated down. return JsonParser.parseString(new Gson().toJson(task.getResult().getData())); } }); }درخواست JSON را با تنظیم نوع روی
LABEL_DETECTIONایجاد کنید:Kotlin
// Create json request to cloud vision val request = JsonObject() // Add image to request val image = JsonObject() image.add("content", JsonPrimitive(base64encoded)) request.add("image", image) // Add features to the request val feature = JsonObject() feature.add("maxResults", JsonPrimitive(5)) feature.add("type", JsonPrimitive("LABEL_DETECTION")) val features = JsonArray() features.add(feature) request.add("features", features)Java
// Create json request to cloud vision JsonObject request = new JsonObject(); // Add image to request JsonObject image = new JsonObject(); image.add("content", new JsonPrimitive(base64encoded)); request.add("image", image); //Add features to the request JsonObject feature = new JsonObject(); feature.add("maxResults", new JsonPrimitive(5)); feature.add("type", new JsonPrimitive("LABEL_DETECTION")); JsonArray features = new JsonArray(); features.add(feature); request.add("features", features);درنهایت، تابع را فراخوانی کنید:
Kotlin
annotateImage(request.toString()) .addOnCompleteListener { task -> if (!task.isSuccessful) { // Task failed with an exception // ... } else { // Task completed successfully // ... } }Java
annotateImage(request.toString()) .addOnCompleteListener(new OnCompleteListener<JsonElement>() { @Override public void onComplete(@NonNull Task<JsonElement> task) { if (!task.isSuccessful()) { // Task failed with an exception // ... } else { // Task completed successfully // ... } } });
۳. دریافت اطلاعات درباره اشیای برچسبگذاریشده
اگر عملیات برچسبگذاری تصویر موفقیتآمیز باشد، پاسخ JSON BatchAnnotateImagesResponse در نتیجه تکلیف برگردانده خواهد شد. هر شیء در آرایهlabelAnnotations
نشاندهنده چیزی است که در تصویر برچسبگذاری شده است. برای هر برچسب، میتوانید
توضیحات نوشتاری برچسب،
شناسه نهاد Knowledge Graph آن
(درصورت وجود)، و امتیاز اطمینان مطابقت را دریافت کنید. برای مثال:
Kotlin
for (label in task.result!!.asJsonArray[0].asJsonObject["labelAnnotations"].asJsonArray) {
val labelObj = label.asJsonObject
val text = labelObj["description"]
val entityId = labelObj["mid"]
val confidence = labelObj["score"]
}
Java
for (JsonElement label : task.getResult().getAsJsonArray().get(0).getAsJsonObject().get("labelAnnotations").getAsJsonArray()) {
JsonObject labelObj = label.getAsJsonObject();
String text = labelObj.get("description").getAsString();
String entityId = labelObj.get("mid").getAsString();
float score = labelObj.get("score").getAsFloat();
}