برای فراخوانی یک API گوگل کلود از برنامه خود، باید یک API REST واسط ایجاد کنید که مجوزها را مدیریت کرده و از مقادیر مخفی مانند کلیدهای API محافظت کند. سپس باید در برنامه تلفن همراه خود کدی بنویسید تا احراز هویت شده و با این سرویس واسط ارتباط برقرار کند.
یک راه برای ایجاد این REST API استفاده از Firebase Authentication and Functions است که یک دروازه مدیریتشده و بدون سرور به APIهای Google Cloud در اختیار شما قرار میدهد که احراز هویت را مدیریت میکند و میتوان آن را از طریق برنامه تلفن همراه شما با SDKهای از پیش ساخته شده فراخوانی کرد.
این راهنما نحوه استفاده از این تکنیک را برای فراخوانی API Cloud Vision از برنامه شما نشان میدهد. این روش به همه کاربران احراز هویت شده اجازه میدهد تا از طریق پروژه Cloud شما به سرویسهای دارای صورتحساب Cloud Vision دسترسی پیدا کنند، بنابراین قبل از ادامه، در نظر بگیرید که آیا این مکانیسم احراز هویت برای مورد استفاده شما کافی است یا خیر.
قبل از اینکه شروع کنی
پروژه خود را پیکربندی کنید
- اگر هنوز Firebase را به پروژه اندروید خود اضافه نکردهاید، آن را اضافه کنید.
اگر هنوز APIهای مبتنی بر ابر را برای پروژه خود فعال نکردهاید، اکنون این کار را انجام دهید:
- صفحه Firebase ML APIs را در کنسول Firebase باز کنید.
اگر هنوز پروژه خود را به طرح قیمتگذاری پرداخت در محل Blaze ارتقا ندادهاید، برای انجام این کار روی ارتقا کلیک کنید. (فقط در صورتی که پروژه شما در طرح قیمتگذاری Blaze نباشد، از شما خواسته میشود که آن را ارتقا دهید.)
فقط پروژههای موجود در طرح قیمتگذاری Blaze میتوانند از APIهای مبتنی بر ابر استفاده کنند.
- اگر APIهای مبتنی بر ابر از قبل فعال نشدهاند، روی فعال کردن APIهای مبتنی بر ابر کلیک کنید.
- کلیدهای API فایربیس موجود خود را پیکربندی کنید تا دسترسی به API کلود ویژن را غیرفعال کنید:
- صفحه اعتبارنامهها (Credentials) کنسول Cloud را باز کنید.
- برای هر کلید API موجود در لیست، نمای ویرایش را باز کنید و در بخش محدودیتهای کلید، تمام APIهای موجود به جز API Cloud Vision را به لیست اضافه کنید.
تابع قابل فراخوانی را مستقر کنید
در مرحله بعد، تابع ابری (Cloud Function) را که برای ایجاد پل بین برنامه خود و API Cloud Vision استفاده خواهید کرد، مستقر کنید. مخزن functions-samples شامل مثالی است که میتوانید از آن استفاده کنید.
به طور پیشفرض، دسترسی به API Cloud Vision از طریق این تابع، فقط به کاربران احراز هویت شده برنامه شما اجازه دسترسی به API Cloud Vision را میدهد. میتوانید این تابع را برای الزامات مختلف تغییر دهید.
برای استقرار تابع:
- مخزن 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:22.1.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 فراخوانی کنید.ابتدا، یک نمونه از توابع ابری را مقداردهی اولیه کنید:
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 نشاندهندهی چیزی است که در تصویر برچسبگذاری شده است. برای هر برچسب، میتوانید توضیحات متنی برچسب، شناسهی موجودیت نمودار دانش آن (در صورت وجود) و امتیاز اطمینان تطابق را دریافت کنید. برای مثال: 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();
}