Call Vision API Product Search در اندروید

1. قبل از شروع

bd8c01b2f8013c6d.png

آیا دموی Google Lens را دیده‌اید، که در آن می‌توانید دوربین تلفن خود را به سمت یک شی بگیرید و مکان خرید آنلاین آن را پیدا کنید؟ اگر می خواهید یاد بگیرید که چگونه می توانید همان ویژگی را به برنامه خود اضافه کنید، این کد لبه برای شما مناسب است. این بخشی از یک مسیر یادگیری است که به شما می آموزد چگونه یک ویژگی جستجوی تصویر محصول را در یک برنامه تلفن همراه بسازید.

در این کد لبه، یاد خواهید گرفت که چگونه از یک برنامه تلفن همراه با یک Backend ساخته شده با Vision API Product Search فراخوانی کنید. این باطن می‌تواند یک تصویر پرس و جو بگیرد و محصولات مشابه بصری را از کاتالوگ محصول جستجو کند.

می‌توانید در مورد مراحل باقی‌مانده ساخت یک ویژگی جستجوی محصول بصری، از جمله نحوه استفاده از ML Kit Object Detection و Tracking برای شناسایی اشیاء در تصویر جستجو و اجازه دادن به کاربران برای انتخاب محصولی که می‌خواهند جستجو کنند، در مسیر یادگیری اطلاعات کسب کنید.

چیزی که خواهی ساخت

  • در این کد لبه، شما با برنامه اندرویدی شروع می‌کنید که می‌تواند اشیا را از یک تصویر ورودی تشخیص دهد. شما کدی می نویسید تا شیئی را که کاربر انتخاب می کند، بگیرد، آن را به بخش جستجوی محصول بفرستید و نتیجه جستجو را روی صفحه نمایش دهید.
  • در پایان باید چیزی شبیه به تصویر سمت راست ببینید.

چیزی که یاد خواهید گرفت

  • نحوه فراخوانی و تجزیه پاسخ Vision API Product Search API از یک برنامه اندروید

آنچه شما نیاز دارید

  • نسخه اخیر اندروید استودیو (نسخه 4.1.2 و بالاتر)
  • شبیه ساز Android Studio یا یک دستگاه فیزیکی اندروید
  • کد نمونه
  • دانش اولیه توسعه اندروید در Kotlin

این Codelab بر روی Vision API Product Search متمرکز شده است. مفاهیم غیر مرتبط و بلوک های کد کاوش نمی شوند و برای شما ارائه می شوند تا به سادگی کپی و جایگذاری کنید.

2. درباره Vision API Product Search

Vision API Product Search یک ویژگی در Google Cloud است که به کاربران امکان می دهد محصولات مشابه بصری را از کاتالوگ محصولات جستجو کنند. خرده فروشان می توانند محصولاتی ایجاد کنند که هر کدام حاوی تصاویر مرجعی است که به صورت بصری محصول را از مجموعه ای از دیدگاه ها توصیف می کند. سپس می توانید این محصولات را به مجموعه محصولات (یعنی کاتالوگ محصولات) اضافه کنید. در حال حاضر Vision API Product Search از دسته بندی محصولات زیر پشتیبانی می کند: کالاهای خانگی، پوشاک، اسباب بازی، کالاهای بسته بندی شده و عمومی.

هنگامی که کاربران مجموعه محصول را با تصاویر خود پرس و جو می کنند، Vision API Product Search از یادگیری ماشینی برای مقایسه محصول در تصویر جستجوی کاربر با تصاویر موجود در مجموعه محصول خرده فروش استفاده می کند و سپس فهرست رتبه بندی شده ای از نتایج مشابه بصری و معنایی را برمی گرداند.

3. برنامه استارتر را دانلود و اجرا کنید

کد را دانلود کنید

برای دانلود تمامی کدهای این کد لبه روی لینک زیر کلیک کنید:

فایل فشرده دانلود شده را باز کنید. با این کار یک پوشه ریشه ( odml-pathways-main ) با تمام منابعی که نیاز دارید باز می شود. برای این کد لبه، شما فقط به منابع موجود در فهرست فرعی product-search/codelab2/android نیاز دارید.

زیر شاخه codelab2 در مخزن odml-pathways شامل دو فهرست است:

  • android_studio_folder.png starter — کد شروعی که برای این Codelab بر اساس آن می سازید.
  • android_studio_folder.png نهایی - کد تکمیل شده برای برنامه نمونه تمام شده.

برنامه شروع در اینجا برنامه ای است که شما برای ایجاد جستجوی محصول بصری در Detect Objects در تصاویر ساخته اید: Android Codelab. از ML Kit Object Detection و Tracking برای تشخیص اشیاء از یک تصویر و نشان دادن آنها بر روی صفحه استفاده می کند.

برنامه را به اندروید استودیو وارد کنید

با وارد کردن برنامه شروع به Android Studio شروع کنید.

به Android Studio بروید، Import Project (Gradle، Eclipse ADT، و غیره) را انتخاب کنید و پوشه starter را از کد منبعی که قبلا دانلود کرده اید انتخاب کنید.

7c0f27882a2698ac.png

برنامه استارتر را اجرا کنید

اکنون که پروژه را به اندروید استودیو وارد کرده اید، برای اولین بار آماده اجرای برنامه هستید. دستگاه اندروید خود را از طریق USB به هاست خود وصل کنید یا شبیه ساز Android Studio را راه اندازی کنید و روی Run کلیک کنید ( execute.png ) در نوار ابزار Android Studio.

(اگر این دکمه غیرفعال است، مطمئن شوید که فقط starter/app/build.gradle را وارد کرده اید، نه کل مخزن.)

اکنون برنامه باید روی دستگاه اندرویدی شما راه اندازی می شد. در حال حاضر قابلیت تشخیص شی را دارد: موارد مد را از روی تصویر تشخیص می دهد و به شما نشان می دهد که کجا هستند. برای تایید، عکس های از پیش تعیین شده را امتحان کنید.

c6102a808fdfcb11.png

تصویری از برنامه شروع که می تواند اشیاء را در یک تصویر تشخیص دهد

در مرحله بعد، برنامه را گسترش می دهید تا اشیاء شناسایی شده را به پشتیبان جستجوی محصول Vision API ارسال کند و نتایج جستجو را روی صفحه نمایش دهد.

4. انتخاب شی را کنترل کنید

به کاربران اجازه دهید برای انتخاب روی یک شی شناسایی شده ضربه بزنند

اکنون کدی را اضافه می‌کنید تا به کاربران اجازه دهید یک شی را از تصویر انتخاب کنند و جستجوی محصول را شروع کنند. برنامه شروع از قبل قابلیت تشخیص اشیاء در تصویر را دارد. این امکان وجود دارد که چندین شی در تصویر وجود داشته باشد، یا جسم شناسایی شده تنها بخش کوچکی از تصویر را اشغال کند. بنابراین، باید از کاربر بخواهید روی یکی از اشیاء شناسایی شده ضربه بزند تا نشان دهد که از کدام شی می‌خواهد برای جستجوی محصول استفاده کند.

9cdfcead6d95a87.png

اسکرین شات از آیتم های مد شناسایی شده از تصویر

برای ساده نگه داشتن و متمرکز نگه داشتن نرم افزار کد روی یادگیری ماشینی، برخی از کدهای اندرویدی دیگ بخاری در برنامه استارت پیاده سازی شده است تا به شما کمک کند تشخیص دهید کاربر روی کدام شی ضربه زده است. نمایی که تصویر را در اکتیویتی اصلی نمایش می دهد ( ObjectDetectorActivity ) در واقع یک نمای سفارشی ( ImageClickableView ) است که ImageView پیش فرض سیستم عامل اندروید را گسترش می دهد. برخی از روش‌های کاربردی راحت را اجرا می‌کند، از جمله:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) این یک تماس برای دریافت تصویر برش خورده است که فقط شامل شیئی است که کاربر روی آن ضربه زده است. شما این تصویر برش خورده را به بخش جستجوی محصول ارسال خواهید کرد.

برای رسیدگی به ضربه زدن کاربر روی اشیاء شناسایی شده کد اضافه کنید.

به متد initViews در کلاس ObjectDetectorActivity و این خطوط را در انتهای متد اضافه کنید: (اندروید استودیو به شما می گوید که نمی تواند متد startProductImageSearch را پیدا کند startProductImageSearch نگران نباشید، کمی بعد آن را پیاده سازی می کنید.)

// Callback received when the user taps on any of the detected objects.
ivPreview.setOnObjectClickListener { objectImage ->
    startProductImageSearch(objectImage)
}

هنگامی که کاربر روی هر یک از اشیاء شناسایی شده روی صفحه ضربه می زند، onObjectClickListener فراخوانی می شود. تصویر برش خورده را دریافت می کند که فقط شامل شی انتخاب شده است. برای مثال، اگر کاربر روی شخصی که لباس سمت راست پوشیده است ضربه بزند، شنونده با objectImage مانند زیر فعال می شود.

9cac8458d0f326e6.png

نمونه ای از تصویر برش داده شده به onObjectClickListener

تصویر برش خورده را به فعالیت جستجوی محصول ارسال کنید

اکنون منطق ارسال تصویر پرس و جو را به پشتوانه جستجوی محصول Vision API در یک فعالیت مجزا ( ProductSearchActivity ) پیاده سازی خواهید کرد.

همه اجزای رابط کاربری از قبل پیاده سازی شده اند، بنابراین می توانید روی نوشتن کد برای برقراری ارتباط با بخش جستجوی محصول تمرکز کنید.

25939f5a13eeb3c3.png

تصویری از اجزای رابط کاربری در ProductSearchActivity

کدی را برای ارسال تصویر شی که کاربر انتخاب کرده است به ProductSearchActivity کنید.

به Android Studio برگردید و این متد startProductImageSearch را به کلاس ObjectDetectorActivity اضافه کنید:

private fun startProductImageSearch(objectImage: Bitmap) {
    try {
        // Create file based Bitmap. We use PNG to preserve the image quality
        val savedFile = createImageFile(ProductSearchActivity.CROPPED_IMAGE_FILE_NAME)
        objectImage.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(savedFile))

        // Start the product search activity (using Vision Product Search API.).
        startActivity(
            Intent(
                    this,
                    ProductSearchActivity::class.java
            ).apply {
                // As the size limit of a bundle is 1MB, we need to save the bitmap to a file
                // and reload it in the other activity to support large query images.
                putExtra(
                    ProductSearchActivity.REQUEST_TARGET_IMAGE_PATH,
                    savedFile.absolutePath
                )
            })
    } catch (e: Exception) {
        // IO Exception, Out Of memory ....
        Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
        Log.e(TAG, "Error starting the product image search activity.", e)
    }
}

قطعه کد 3 کار را انجام می دهد:

  • تصویر برش خورده را می گیرد و آن را به یک فایل PNG سریالی می کند.
  • ProductSearchActivity را برای اجرای دنباله جستجوی محصول شروع می کند.
  • URI تصویر برش‌خورده را در هدف شروع فعالیت شامل می‌شود تا ProductSearchActivity بتواند بعداً آن را برای استفاده به عنوان تصویر جستجو بازیابی کند.

چند نکته وجود دارد که باید در نظر داشت:

  • منطق تشخیص اشیاء و پرس و جو از باطن به 2 فعالیت تقسیم شده است تا درک راحت‌تر از Codelab انجام شود. این شما هستید که تصمیم می گیرید چگونه آنها را در برنامه خود پیاده سازی کنید.
  • شما باید تصویر پرس و جو را در یک فایل بنویسید و URI تصویر را بین فعالیت ها ارسال کنید، زیرا تصویر پرس و جو می تواند بزرگتر از محدودیت اندازه 1 مگابایت یک هدف اندروید باشد.
  • شما می توانید تصویر پرس و جو را در PNG ذخیره کنید زیرا یک فرمت بدون ضرر است.

تصویر پرس و جو را در فعالیت جستجوی محصول بازیابی کنید

در ProductSearchActivity ، کد بازیابی تصویر پرس و جو و نمایش آن بر روی صفحه، قبلاً در برنامه شروع اجرا شده است.

به روش onCreate بروید و تأیید کنید که این کد از قبل وجود دارد:

// Receive the query image and show it on the screen
intent.getStringExtra(REQUEST_TARGET_IMAGE_PATH)?.let { absolutePath ->
    viewBinding.ivQueryImage.setImageBitmap(BitmapFactory.decodeFile(absolutePath))
}

برنامه را اجرا کنید

حالا روی Run کلیک کنید ( execute.png ) در نوار ابزار Android Studio.

پس از بارگیری برنامه، روی هر تصویر از پیش تعیین شده ضربه بزنید و یکی از اشیاء شناسایی شده را انتخاب کنید.

تأیید کنید که ProductSearchActivity با تصویری که روی آن ضربه زده اید نشان داده می شود. دکمه جستجو هنوز کاری انجام نمی دهد اما در مرحله بعد آن را اجرا خواهیم کرد.

fed40f81b8b43801.png

پس از ضربه زدن بر روی یکی از اشیاء شناسایی شده باید صفحه مشابهی را مشاهده کنید.

5. بخش جستجوی محصول را کاوش کنید

باطن جستجوی تصویر محصول را بسازید

این آزمایشگاه کد به یک پشتیبان جستجوی محصول نیاز دارد که با Vision API Product Search ساخته شده است. برای رسیدن به این هدف دو گزینه وجود دارد:

گزینه 1: از پشتیبان نسخه ی نمایشی استفاده کنید که برای شما مستقر شده است

می‌توانید با استفاده از پشتیبان جستجوی محصول که Google قبلاً برای شما ایجاد کرده است، با این کد لبه کار کنید. باطن نسخه ی نمایشی را می توان با دنبال کردن راه اندازی سریع محصول Vision API تکرار کرد.

گزینه 2: با دنبال کردن راه اندازی سریع محصول Vision API، باطن خود را ایجاد کنید

این گزینه برای کسانی توصیه می‌شود که می‌خواهند در مورد نحوه ایجاد یک backend جستجوی محصول به طور عمیق بیاموزند تا بتوانید بعداً برای کاتالوگ محصول خود یکی بسازید. باید داشته باشی:

  • یک حساب Google Cloud با فعال کردن صورت‌حساب. (این می تواند یک حساب آزمایشی رایگان باشد.)
  • برخی از دانش در مورد مفاهیم Google Cloud، از جمله پروژه ها، حساب های خدمات و غیره.

می توانید نحوه انجام این کار را بعداً در مسیر یادگیری بیاموزید.

مفاهیم مهم را یاد بگیرید

هنگام تعامل با بخش جستجوی محصول با این مفاهیم روبرو خواهید شد:

  • مجموعه محصول: مجموعه محصول ظرفی ساده برای گروهی از محصولات است. یک کاتالوگ محصول را می توان به عنوان یک مجموعه محصول و محصولات آن نشان داد.
  • محصول : پس از ایجاد یک مجموعه محصول، می توانید محصولاتی ایجاد کرده و آنها را به مجموعه محصول اضافه کنید.
  • تصاویر مرجع محصول: این تصاویر حاوی نماهای مختلف از محصولات شما هستند. از تصاویر مرجع برای جستجوی محصولات مشابه بصری استفاده می شود.
  • جستجوی محصولات : هنگامی که مجموعه محصول خود را ایجاد کردید و مجموعه محصول نمایه شد، می توانید مجموعه محصول را با استفاده از Cloud Vision API جستجو کنید.

کاتالوگ محصولات از پیش تعیین شده را درک کنید

بخش نمایشی جستجوی محصول مورد استفاده در این کد لبه با استفاده از Vision API Product Search و یک کاتالوگ محصول از حدود صد تصویر کفش و لباس ایجاد شده است. در اینجا چند تصویر از کاتالوگ آمده است:

4f1a8507b74ab178.png79a5fc6c829eca77.png3528c872f813826e.png

نمونه هایی از کاتالوگ محصولات از پیش تعیین شده

با بخش نمایشی جستجوی محصول تماس بگیرید

می‌توانید با راه‌اندازی یک کلید Google Cloud API و محدود کردن دسترسی به کلید API فقط به برنامه خود، مستقیماً از یک برنامه تلفن همراه با جستجوی محصول Vision API تماس بگیرید.

برای ساده نگه داشتن این کد، یک نقطه پایانی پروکسی تنظیم شده است که به شما امکان می دهد بدون نگرانی در مورد کلید API و احراز هویت، به پشتیبان دمو دسترسی داشته باشید. درخواست HTTP را از برنامه تلفن همراه دریافت می‌کند، کلید API را اضافه می‌کند و درخواست را به پشتیبان جستجوی محصول Vision API ارسال می‌کند. سپس پروکسی پاسخ را از باطن دریافت می کند و آن را به برنامه تلفن همراه برمی گرداند.

در این لبه کد، از دو API از Vision API Product Search استفاده خواهید کرد:

  • projects.locations.images.annotate : ارسال تصویر پرس و جو به سرور و دریافت لیستی از محصولات از کاتالوگ محصول از پیش تعیین شده که از نظر بصری مشابه تصویر درخواستی است.
  • projects.locations.products.referenceImages.get : دریافت URI تصاویر محصول که در فراخوانی API بالا برای نمایش به کاربران بازگردانده شده است.

6. کلاینت API را پیاده سازی کنید

گردش کار جستجوی محصول را درک کنید

برای انجام جستجوی محصول با باطن این گردش کار را دنبال کنید:

  • تصویر پرس و جو را به عنوان یک رشته base64 رمزگذاری کنید
  • projects.locations.images.annotate را با تصویر پرس و جو فراخوانی کنید
  • شناسه‌های تصویر محصول را از تماس API قبلی دریافت کنید و آنها را به نقاط پایانی projects.locations.products.referenceImages.get ارسال کنید تا URI تصاویر محصول را در نتیجه جستجو دریافت کنید.

کلاس کلاینت API را پیاده سازی کنید

اکنون کدی را برای فراخوانی باطن جستجوی محصول در یک کلاس اختصاصی به نام ProductSearchAPIClient پیاده سازی خواهید کرد. برخی از کدهای دیگ بخار در برنامه استارت برای شما پیاده سازی شده است:

  • class ProductSearchAPIClient : این کلاس در حال حاضر اکثراً خالی است، اما متدهایی دارد که بعداً در این Codelab پیاده‌سازی خواهید کرد.
  • fun convertBitmapToBase64(bitmap: Bitmap) : یک نمونه بیت مپ را به نمایش base64 آن تبدیل کنید تا به بخش جستجوی محصول ارسال شود.
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>> : projects.locations.images.annotate API را فراخوانی کنید و پاسخ را تجزیه کنید.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult> : projects.locations.products.referenceImages.get API را فراخوانی کنید و پاسخ را تجزیه کنید.
  • SearchResult.kt : این فایل حاوی چندین کلاس داده است تا انواع بازگردانده شده توسط Vision API Product Search را نشان دهد.

تنظیمات API را مشخص کنید

به کلاس ProductSearchAPIClient و برخی از تنظیمات مربوط به جستجوی محصول را که قبلاً تعریف شده است مشاهده خواهید کرد:

// Define the product search backend
// Option 1: Use the demo project that we have already deployed for you
const val VISION_API_URL =
    "https://us-central1-odml-codelabs.cloudfunctions.net/productSearch"
const val VISION_API_KEY = ""
const val VISION_API_PROJECT_ID = "odml-codelabs"
const val VISION_API_LOCATION_ID = "us-east1"
const val VISION_API_PRODUCT_SET_ID = "product_set0"
  • VISION_API_URL نقطه پایانی API Cloud Vision API است. همانطور که با نسخه آزمایشی پیش می روید، آن را روی نقطه پایانی پروکسی تنظیم کنید. با این حال، اگر باطن خود را مستقر کنید، باید آن را به نقطه پایانی Cloud Vision API تغییر دهید. https://vision.googleapis.com/v1 .
  • VISION_API_KEY کلید API پروژه Cloud شما است. از آنجایی که پروکسی قبلاً احراز هویت را انجام می دهد، می توانید این قسمت را خالی بگذارید.
  • VISION_API_PROJECT_ID شناسه پروژه Cloud است. odml-codelabs پروژه Cloud است که در آن باطن دمو مستقر شده است.
  • VISION_API_LOCATION_ID مکان Cloud است که پشتیبان جستجوی محصول در آن مستقر شده است. us-east1 جایی است که ما باطن نسخه ی نمایشی را اجرا کردیم.
  • VISION_API_PRODUCT_SET_ID شناسه کاتالوگ محصول (معروف به "مجموعه محصول" در عبارت Vision API) است که در آن می خواهید محصولات مشابه بصری را جستجو کنید. می توانید چندین کاتالوگ در یک پروژه Cloud داشته باشید. product_set0 کاتالوگ محصول از پیش تعیین شده از نسخه آزمایشی باطن است.

7. با API جستجوی محصول تماس بگیرید

فرمت درخواست و پاسخ API را کاوش کنید

می‌توانید با ارسال URI Google Cloud Storage، URL وب یا رشته رمزگذاری‌شده base64 به Vision API محصول، محصولات مشابه یک تصویر را پیدا کنید. در این لبه کد، از گزینه رشته رمزگذاری شده base64 استفاده خواهید کرد، زیرا تصویر درخواست ما فقط در دستگاه کاربر وجود دارد.

شما باید یک درخواست POST را با بدنه JSON درخواست به projects.locations.images.annotate ارسال کنید:

{
  "requests": [
    {
      "image": {
        "content": {base64-encoded-image}
      },
      "features": [
        {
          "type": "PRODUCT_SEARCH",
          "maxResults": 5
        }
      ],
      "imageContext": {
        "productSearchParams": {
          "productSet": "projects/{project-id}/locations/{location-id}/productSets/{product-set-id}",
          "productCategories": [
               "apparel-v2"
          ],
        }
      }
    }
  ]
}

برخی از پارامترها وجود دارد که باید مشخص شوند:

  • base64-encoded-image : نمایش base64 (رشته ASCII) از داده های باینری تصویر پرس و جو.
  • project-id : شناسه پروژه GCP شما.
  • location-id : یک شناسه مکان معتبر.
  • product-set-id : شناسه مجموعه محصولی که می خواهید عملیات را روی آن اجرا کنید.

از آنجایی که کاتالوگ محصول شما فقط شامل کفش ها و تصاویر لباس است، دسته بندی محصول را به عنوان apparel apparel-v2 مشخص کنید. v2 در اینجا به این معنی است که ما از نسخه 2 مدل یادگیری ماشین جستجوی محصولات پوشاک استفاده می کنیم.

اگر درخواست موفقیت آمیز باشد، سرور یک کد وضعیت HTTP 200 OK و پاسخ را در قالب JSON برمی‌گرداند. پاسخ JSON شامل دو نوع نتیجه زیر است:

  • productSearch Results - حاوی لیستی از محصولات منطبق برای کل تصویر است.
  • productGroupedResults - شامل مختصات جعبه محدود و موارد منطبق برای هر محصول مشخص شده در تصویر است.

از آنجایی که محصول قبلاً از تصویر اصلی برش داده شده است، نتایج را در لیست productSearchResults تجزیه خواهید کرد.

در اینجا چند فیلد مهم در شیء نتیجه جستجوی محصول آمده است:

  • product.name : شناسه منحصربه‌فرد یک محصول در قالب projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score : مقداری که نشان می دهد نتیجه جستجو چقدر شبیه به تصویر درخواست است. مقادیر بالاتر به معنای شباهت بیشتر است.
  • product.image : شناسه منحصربه‌فرد تصویر مرجع یک محصول در قالب projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id} . برای دریافت URL این تصویر مرجع، باید درخواست API دیگری را به projects.locations.products.referenceImages.get ارسال کنید تا روی صفحه نمایش داده شود.
  • product.labels : فهرستی از برچسب های از پیش تعریف شده محصول. اگر می‌خواهید نتایج جستجو را فیلتر کنید تا فقط یک دسته از لباس‌ها مانند لباس‌ها را نشان دهید، این کار مفید است.

تصویر پرس و جو را به base64 تبدیل کنید

باید تصویر query را به نمایش رشته base64 تبدیل کنید و رشته را به شی JSON در بدنه درخواست متصل کنید.

به کلاس ProductSearchAPIClient ، متد خالی convertBitmapToBase64 را پیدا کنید و آن را با این پیاده سازی جایگزین کنید:

private fun convertBitmapToBase64(bitmap: Bitmap): String {
    val byteArrayOutputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
    val byteArray: ByteArray = byteArrayOutputStream.toByteArray()
    return Base64.encodeToString(byteArray, Base64.DEFAULT)
}

فراخوانی API را اجرا کنید

بعد، یک درخواست API جستجوی محصول ایجاد کنید و آن را به باطن ارسال کنید. از Volley برای درخواست API استفاده می‌کنید و نتیجه را با استفاده از Task API برمی‌گردانید.

به کلاس ProductSearchAPIClient ، متد خالی annotateImage را پیدا کنید و آن را با این پیاده سازی جایگزین کنید:

fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<List<ProductSearchResult>>()
    val apiTask = apiSource.task

    // Convert the query image to its Base64 representation to call the Product Search API.
    val base64: String = convertBitmapToBase64(image)

    // Craft the request body JSON.
    val requestJson = """
        {
          "requests": [
            {
              "image": {
                "content": """".trimIndent() + base64 + """"
              },
              "features": [
                {
                  "type": "PRODUCT_SEARCH",
                  "maxResults": $VISION_API_PRODUCT_MAX_RESULT
                }
              ],
              "imageContext": {
                "productSearchParams": {
                  "productSet": "projects/${VISION_API_PROJECT_ID}/locations/${VISION_API_LOCATION_ID}/productSets/${VISION_API_PRODUCT_SET_ID}",
                  "productCategories": [
                       "apparel-v2"
                     ]
                }
              }
            }
          ]
        }
    """.trimIndent()

    // Add a new request to the queue
    requestQueue.add(object :
        JsonObjectRequest(
            Method.POST,
            "$VISION_API_URL/images:annotate?key=$VISION_API_KEY",
            JSONObject(requestJson),
            { response ->
                // Parse the API JSON response to a list of ProductSearchResult object/
                val productList = apiResponseToObject(response)

                // Return the list.
                apiSource.setResult(productList)
            },
            // Return the error
            { error -> apiSource.setException(error) }
        ) {
        override fun getBodyContentType() = "application/json"
    }.apply {
        setShouldCache(false)
    })

    return apiTask
}

نتیجه جستجو را در UI نشان دهید

اکنون کد API در ProductSearchAPIClient آماده است. برای پیاده سازی کد UI به Activity ProductSearchActivity .

این اکتیویتی قبلاً دارای کدهای دیگ بخاری است که searchByImage(queryImage: Bitmap) را راه‌اندازی می‌کند. کدی را برای فراخوانی باطن و نمایش نتایج در UI به این روش خالی فعلی اضافه کنید.

apiClient.annotateImage(queryImage)
    .addOnSuccessListener { showSearchResult(it) }
    .addOnFailureListener { error ->
        Log.e(TAG, "Error calling Vision API Product Search.", error)
        showErrorResponse(error.localizedMessage)
    }

متد showSearchResult حاوی کدهای دیگ بخار است که پاسخ API را تجزیه می کند و آنها را روی صفحه برای شما نشان می دهد.

آن را اجرا کنید

حالا روی Run کلیک کنید ( execute.png ) در نوار ابزار Android Studio. پس از بارگیری برنامه، روی هر تصویر از پیش تعیین شده ضربه بزنید، یک شی شناسایی شده را انتخاب کنید، روی دکمه جستجو ضربه بزنید و نتایج جستجوی بازگشتی را از پشتیبان مشاهده کنید. چیزی شبیه به این خواهید دید:

bb5e7c27c283a2fe.png

اسکرین شات از صفحه نتایج جستجوی محصول

پشتیبان از قبل فهرستی از محصولات مشابه بصری را از کاتالوگ محصولات از پیش تعیین شده برمی گرداند. با این حال، می بینید که تصویر محصول هنوز خالی است. به این دلیل است که نقطه پایانی projects.locations.images.annotate فقط شناسه های تصویر محصول مانند projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77 را برمی گرداند. باید یک تماس API دیگر با projects.locations.products.referenceImages.get نقطه پایانی برقرار کنید و URL این تصویر مرجع را دریافت کنید تا روی صفحه نمایش داده شود.

8. تصاویر مرجع محصول را دریافت کنید

فرمت درخواست و پاسخ API را کاوش کنید

شما یک درخواست GET HTTP با بدنه درخواست خالی به نقطه پایانی projects.locations.products.referenceImages.get ارسال می کنید تا URI تصاویر محصول را که توسط نقطه پایانی جستجوی محصول برگردانده شده است، دریافت کنید.

درخواست HTTP به شکل زیر است:

GET $VISION_API_URL/projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77?key=$VISION_API_KEY

اگر درخواست موفقیت آمیز باشد، سرور یک کد وضعیت HTTP 200 OK و پاسخ را در قالب JSON به شرح زیر برمی گرداند:

{
  "name":"projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77",
  "uri":"gs://cloud-ai-vision-data/product-search-tutorial/images/46991e7370ba11e8a1bbd20059124800.jpg"
}
  • نام : شناسه تصویر مرجع
  • uri : URI تصویر در Google Cloud Storage (GCS).

تصاویر مرجع پشتیبان جستجوی محصول آزمایشی برای داشتن مجوز خواندن عمومی تنظیم شده است. بنابراین، می توانید به راحتی URI GCS را به یک URL HTTP تبدیل کرده و آن را در رابط کاربری برنامه نمایش دهید. فقط باید پیشوند gs:// را با https://storage.googleapis.com/ جایگزین کنید.

فراخوانی API را اجرا کنید

بعد، یک درخواست API جستجوی محصول ایجاد کنید و آن را به باطن ارسال کنید. شما از Volley و Task API مشابه تماس API جستجوی محصول استفاده خواهید کرد.

به کلاس ProductSearchAPIClient ، متد خالی fetchReferenceImage را پیدا کنید و آن را با این پیاده سازی جایگزین کنید:

private fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<ProductSearchResult>()
    val apiTask = apiSource.task

    // Craft the API request to get details about the reference image of the product
    val stringRequest = object : StringRequest(
        Method.GET,
        "$VISION_API_URL/${searchResult.imageId}?key=$VISION_API_KEY",
        { response ->
            val responseJson = JSONObject(response)
            val gcsUri = responseJson.getString("uri")

            // Convert the GCS URL to its HTTPS representation
            val httpUri = gcsUri.replace("gs://", "https://storage.googleapis.com/")

            // Save the HTTPS URL to the search result object
            searchResult.imageUri = httpUri

            // Invoke the listener to continue with processing the API response (eg. show on UI)
            apiSource.setResult(searchResult)
        },
        { error -> apiSource.setException(error) }
    ) {

        override fun getBodyContentType(): String {
            return "application/json; charset=utf-8"
        }
    }
    Log.d(ProductSearchActivity.TAG, "Sending API request.")

    // Add the request to the RequestQueue.
    requestQueue.add(stringRequest)

    return apiTask
}

این روش یک SearchResult را می گیرد searchResult: ProductSearchResult که توسط نقطه پایانی جستجوی محصول برگردانده شده است و سپس این مراحل را دنبال می کند:

  1. نقطه پایانی تصویر مرجع را برای دریافت URI GCS تصویر مرجع فراخوانی می کند.
  2. URI GCS را به URL HTTP تبدیل می کند.
  3. ویژگی httpUri شی searchResult را با این URL HTTP به روز می کند.

دو درخواست API را به هم وصل کنید

به annotateImage برگردید و آن را تغییر دهید تا همه URL های HTTP تصاویر مرجع را قبل از بازگرداندن لیست ProductSearchResult به تماس گیرنده آن، دریافت کنید.

این خط را پیدا کنید:

// Return the list.
apiSource.setResult(productList)

سپس آن را با این پیاده سازی جایگزین کنید:

// Loop through the product list and create tasks to load reference images.
// We will call the projects.locations.products.referenceImages.get endpoint
// for each product.
val fetchReferenceImageTasks = productList.map { fetchReferenceImage(it) }

// When all reference image fetches have completed,
// return the ProductSearchResult list
Tasks.whenAllComplete(fetchReferenceImageTasks)
    // Return the list of ProductSearchResult with product images' HTTP URLs.
    .addOnSuccessListener { apiSource.setResult(productList) }
    // An error occurred so returns it to the caller.
    .addOnFailureListener { apiSource.setException(it) }

کد دیگ بخار برای نمایش تصاویر مرجع روی صفحه از قبل در کلاس ProductSearchAdapter برای شما پیاده سازی شده است، بنابراین می توانید به اجرای مجدد برنامه ادامه دهید.

آن را اجرا کنید

حالا روی Run کلیک کنید ( execute.png ) در نوار ابزار Android Studio. پس از بارگیری برنامه، روی هر تصویر از پیش تعیین شده ضربه بزنید، یک شی شناسایی شده را انتخاب کنید، روی دکمه جستجو ضربه بزنید تا نتایج جستجو را مشاهده کنید، این بار با تصاویر محصول.

آیا نتایج جستجوی محصول برای شما منطقی است؟

25939f5a13eeb3c3.png

9. تبریک می گویم!

شما یاد گرفته‌اید که چگونه با ویژن API جستجوی محصول تماس بگیرید تا قابلیت جستجوی تصویر محصول را به برنامه Android خود اضافه کنید. این تمام چیزی است که برای راه اندازی آن نیاز دارید!

همانطور که ادامه می دهید، ممکن است دوست داشته باشید با استفاده از کاتالوگ محصولات خود باطن خود را بسازید. برای اینکه یاد بگیرید چگونه می‌توانید باطن خود را بسازید و کلید API را برای فراخوانی آن از یک برنامه تلفن همراه تنظیم کنید، کدهای بعدی را در مسیر یادگیری جستجوی تصویر محصول بررسی کنید.

آنچه را پوشش داده ایم

  • نحوه فراخوانی Vision API Product Search از برنامه اندروید

مراحل بعدی

بیشتر بدانید