เรียกใช้แบ็กเอนด์ของ Vision API Product Search ใน Android

1. ก่อนเริ่มต้น

bd8c01b2f8013c6d.png

คุณเคยเห็นการสาธิต Google Lens ไหม ที่คุณสามารถเล็งกล้องโทรศัพท์ไปยังวัตถุและดูว่าซื้อวัตถุนั้นทางออนไลน์ได้ที่ไหน หากต้องการดูวิธีเพิ่มฟีเจอร์เดียวกันลงในแอป Codelab นี้เหมาะสำหรับคุณ ซึ่งเป็นส่วนหนึ่งของเส้นทางการเรียนรู้ที่จะสอนวิธีสร้างฟีเจอร์ค้นหารูปภาพผลิตภัณฑ์ลงในแอปบนอุปกรณ์เคลื่อนที่

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีเรียกใช้แบ็กเอนด์ที่สร้างด้วย Vision API Product Search จากแอปบนอุปกรณ์เคลื่อนที่ แบ็กเอนด์นี้สามารถรับรูปภาพคำค้นหาและค้นหาผลิตภัณฑ์ที่คล้ายกันในแคตตาล็อกผลิตภัณฑ์

คุณดูขั้นตอนที่เหลือในการสร้างฟีเจอร์การค้นหาผลิตภัณฑ์ด้วยภาพ รวมถึงวิธีใช้การตรวจหาและการติดตามออบเจ็กต์ของ ML Kit เพื่อตรวจหาออบเจ็กต์ในรูปภาพคำค้นหาและให้ผู้ใช้เลือกผลิตภัณฑ์ที่ต้องการค้นหาได้ในเส้นทางการเรียนรู้

สิ่งที่คุณจะสร้าง

  • ใน Codelab นี้ คุณจะเริ่มต้นด้วยแอป Android ที่ตรวจหาออบเจ็กต์จากรูปภาพอินพุตได้ คุณจะเขียนโค้ดเพื่อนำออบเจ็กต์ที่ผู้ใช้เลือก ส่งไปยังแบ็กเอนด์การค้นหาผลิตภัณฑ์ และแสดงผลการค้นหาบนหน้าจอ
  • ในท้ายที่สุด คุณควรเห็นสิ่งที่คล้ายกับรูปภาพทางด้านขวา

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเรียกและแยกวิเคราะห์การตอบกลับของ Vision API Product Search API จากแอป Android

สิ่งที่ต้องมี

  • Android Studio เวอร์ชันล่าสุด (v4.1.2 ขึ้นไป)
  • โปรแกรมจำลอง Android Studio หรืออุปกรณ์ Android จริง
  • โค้ดตัวอย่าง
  • ความรู้พื้นฐานเกี่ยวกับการพัฒนาแอป Android ใน Kotlin

Codelab นี้มุ่งเน้นที่การค้นหาผลิตภัณฑ์ด้วย Vision API เราจะไม่เจาะลึกแนวคิดและบล็อกโค้ดที่ไม่เกี่ยวข้อง แต่จะให้คุณคัดลอกและวางได้เลย

2. เกี่ยวกับ Vision API Product Search

Vision API Product Search เป็นฟีเจอร์ใน Google Cloud ที่ช่วยให้ผู้ใช้ค้นหาผลิตภัณฑ์ที่คล้ายกันในแคตตาล็อกผลิตภัณฑ์ได้ ผู้ค้าปลีกสามารถสร้างผลิตภัณฑ์แต่ละรายการซึ่งมีรูปภาพอ้างอิงที่อธิบายผลิตภัณฑ์ด้วยภาพจากมุมมองต่างๆ จากนั้นคุณจะเพิ่มผลิตภัณฑ์เหล่านี้ลงในชุดผลิตภัณฑ์ (เช่น แคตตาล็อกผลิตภัณฑ์) ได้ ปัจจุบัน Vision API Product Search รองรับหมวดหมู่ผลิตภัณฑ์ต่อไปนี้ ของใช้ในบ้าน เครื่องแต่งกาย ของเล่น สินค้าบรรจุภัณฑ์ และทั่วไป

เมื่อผู้ใช้ค้นหาชุดผลิตภัณฑ์ด้วยรูปภาพของตนเอง การค้นหาผลิตภัณฑ์ของ Vision API จะใช้แมชชีนเลิร์นนิงเพื่อเปรียบเทียบผลิตภัณฑ์ในรูปภาพคำค้นหาของผู้ใช้กับรูปภาพในชุดผลิตภัณฑ์ของผู้ค้าปลีก จากนั้นจะแสดงรายการผลลัพธ์ที่คล้ายกันทั้งในด้านภาพและความหมาย

3. ดาวน์โหลดและเรียกใช้แอปเริ่มต้น

ดาวน์โหลดโค้ด

คลิกลิงก์ต่อไปนี้เพื่อดาวน์โหลดโค้ดทั้งหมดสำหรับ Codelab นี้

คลายไฟล์ ZIP ที่ดาวน์โหลด การดำเนินการนี้จะแตกโฟลเดอร์รูท (odml-pathways-main) พร้อมทรัพยากรทั้งหมดที่คุณต้องการ สำหรับโค้ดแล็บนี้ คุณจะต้องใช้เฉพาะแหล่งที่มาในไดเรกทอรีย่อย product-search/codelab2/android

codelab2 ไดเรกทอรีย่อยในที่เก็บ odml-pathways มี 2 ไดเรกทอรี ดังนี้

  • android_studio_folder.pngstarter - โค้ดเริ่มต้นที่คุณจะใช้ต่อใน Codelab นี้
  • android_studio_folder.pngfinal - โค้ดที่เสร็จสมบูรณ์สำหรับแอปตัวอย่างที่เสร็จสมบูรณ์

แอปเริ่มต้นที่นี่คือแอปที่คุณสร้างขึ้นใน Codelab ตรวจหาออบเจ็กต์ในรูปภาพเพื่อสร้างการค้นหาผลิตภัณฑ์ด้วยภาพ: Android โดยจะใช้การตรวจจับและติดตามวัตถุของ ML Kit เพื่อตรวจหาวัตถุจากรูปภาพและแสดงบนหน้าจอ

นำเข้าแอปไปยัง Android Studio

เริ่มต้นด้วยการนำเข้าแอปเริ่มต้นไปยัง Android Studio

ไปที่ Android Studio เลือกนำเข้าโปรเจ็กต์ (Gradle, Eclipse ADT ฯลฯ) แล้วเลือกโฟลเดอร์ starter จากซอร์สโค้ดที่คุณดาวน์โหลดไว้ก่อนหน้านี้

7c0f27882a2698ac.png

เรียกใช้แอปเริ่มต้น

ตอนนี้คุณได้นำเข้าโปรเจ็กต์ไปยัง Android Studio แล้ว และพร้อมที่จะเรียกใช้แอปเป็นครั้งแรก เชื่อมต่ออุปกรณ์ Android ผ่าน USB กับโฮสต์หรือเริ่มโปรแกรมจำลอง Android Studio แล้วคลิกเรียกใช้ ( execute.png) ในแถบเครื่องมือของ Android Studio

(หากปุ่มนี้ปิดอยู่ ให้ตรวจสอบว่าคุณนำเข้าเฉพาะ starter/app/build.gradle ไม่ใช่ทั้งที่เก็บ)

ตอนนี้แอปควรจะเปิดขึ้นในอุปกรณ์ Android แล้ว โดยมีความสามารถในการตรวจจับวัตถุอยู่แล้ว นั่นคือตรวจจับไอเทมแฟชั่นจากรูปภาพและแสดงให้คุณเห็นว่าไอเทมนั้นอยู่ที่ใด ลองใช้รูปภาพที่ตั้งค่าไว้ล่วงหน้าเพื่อยืนยัน

c6102a808fdfcb11.png

ภาพหน้าจอของแอปเริ่มต้นที่ตรวจจับวัตถุในรูปภาพได้

จากนั้นคุณจะขยายแอปเพื่อส่งออบเจ็กต์ที่ตรวจพบไปยังแบ็กเอนด์การค้นหาผลิตภัณฑ์ของ Vision API และแสดงผลการค้นหาบนหน้าจอ

4. จัดการการเลือกออบเจ็กต์

อนุญาตให้ผู้ใช้แตะออบเจ็กต์ที่ตรวจพบเพื่อเลือก

ตอนนี้คุณจะเพิ่มโค้ดเพื่อให้ผู้ใช้เลือกออบเจ็กต์จากรูปภาพและเริ่มการค้นหาผลิตภัณฑ์ได้ แอปเริ่มต้นมีความสามารถในการตรวจจับออบเจ็กต์ในรูปภาพอยู่แล้ว รูปภาพอาจมีวัตถุหลายอย่าง หรือวัตถุที่ตรวจพบอาจมีขนาดเล็กมากในรูปภาพ ดังนั้น คุณจึงต้องให้ผู้ใช้แตะออบเจ็กต์ที่ตรวจพบรายการใดรายการหนึ่งเพื่อระบุออบเจ็กต์ที่ต้องการใช้ในการค้นหาผลิตภัณฑ์

9cdfcead6d95a87.png

ภาพหน้าจอของไอเทมแฟชั่นที่ตรวจพบจากรูปภาพ

เราได้ติดตั้งใช้งานโค้ด Android แบบ Boilerplate บางส่วนในแอปเริ่มต้นเพื่อช่วยให้คุณตรวจจับได้ว่าผู้ใช้แตะออบเจ็กต์ใด เพื่อให้ Codelab มีความเรียบง่ายและมุ่งเน้นไปที่แมชชีนเลิร์นนิง มุมมองที่แสดงรูปภาพในกิจกรรมหลัก (ObjectDetectorActivity) เป็นมุมมองที่กำหนดเอง (ImageClickableView) ซึ่งขยาย ImageView เริ่มต้นของระบบปฏิบัติการ Android โดยจะใช้เมธอดอรรถประโยชน์ที่สะดวกบางอย่าง ซึ่งรวมถึง

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) นี่คือการเรียกกลับเพื่อรับรูปภาพที่ครอบตัดแล้วซึ่งมีเฉพาะออบเจ็กต์ที่ผู้ใช้แตะ คุณจะส่งรูปภาพที่ครอบตัดนี้ไปยังแบ็กเอนด์การค้นหาผลิตภัณฑ์

เพิ่มโค้ดเพื่อจัดการเมื่อผู้ใช้แตะออบเจ็กต์ที่ตรวจพบ

ไปที่เมธอด initViews ในคลาส ObjectDetectorActivity แล้วเพิ่มบรรทัดต่อไปนี้ที่ส่วนท้ายของเมธอด (Android Studio จะแจ้งว่าหาเมธอด startProductImageSearch ไม่พบ ไม่ต้องกังวล คุณจะติดตั้งใช้งานในภายหลัง

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

ระบบจะเรียกใช้ onObjectClickListener ทุกครั้งที่ผู้ใช้แตะออบเจ็กต์ที่ตรวจพบบนหน้าจอ โดยจะรับรูปภาพที่ครอบตัดแล้วซึ่งมีเฉพาะออบเจ็กต์ที่เลือก เช่น หากผู้ใช้แตะบุคคลที่สวมชุดทางด้านขวา ระบบจะทริกเกอร์ Listener ด้วย objectImage ดังที่แสดงด้านล่าง

9cac8458d0f326e6.png

ตัวอย่างรูปภาพที่ครอบตัดซึ่งส่งไปยัง onObjectClickListener

ส่งรูปภาพที่ครอบตัดไปยังกิจกรรมการค้นหาผลิตภัณฑ์

ตอนนี้คุณจะใช้ตรรกะของการส่งรูปภาพคำค้นหาไปยังแบ็กเอนด์การค้นหาผลิตภัณฑ์ของ Vision API ในกิจกรรมที่แยกต่างหาก (ProductSearchActivity)

เราได้ติดตั้งใช้งานคอมโพเนนต์ UI ทั้งหมดไว้ล่วงหน้าแล้ว คุณจึงมุ่งเน้นไปที่การเขียนโค้ดเพื่อสื่อสารกับแบ็กเอนด์การค้นหาผลิตภัณฑ์ได้

25939f5a13eeb3c3.png

ภาพหน้าจอของคอมโพเนนต์ UI ใน 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 ของรูปภาพที่ครอบตัดไว้ใน Intent ของกิจกรรมเริ่มต้นเพื่อให้ ProductSearchActivity ดึงข้อมูลรูปภาพดังกล่าวได้ในภายหลังเพื่อใช้เป็นรูปภาพคำค้นหา

โปรดคำนึงถึงสิ่งต่อไปนี้

  • เราได้แยกตรรกะสำหรับการตรวจหาออบเจ็กต์และการค้นหาข้อมูลในแบ็กเอนด์ออกเป็น 2 กิจกรรมเพื่อให้ Codelab เข้าใจได้ง่ายขึ้น คุณต้องเป็นผู้กำหนดวิธีใช้ฟีเจอร์เหล่านี้ในแอป
  • คุณต้องเขียนรูปภาพคำค้นหาลงในไฟล์และส่ง URI ของรูปภาพระหว่างกิจกรรม เนื่องจากรูปภาพคำค้นหามีขนาดใหญ่กว่าขีดจำกัดขนาด 1 MB ของ Intent ใน Android ได้
  • คุณจัดเก็บรูปภาพคำค้นหาในรูปแบบ 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))
}

เรียกใช้แอป

ตอนนี้คลิกเรียกใช้ ( execute.png) ในแถบเครื่องมือ Android Studio

เมื่อแอปโหลดแล้ว ให้แตะรูปภาพที่กำหนดล่วงหน้า แล้วเลือกออบเจ็กต์ที่ตรวจพบ

ตรวจสอบว่า ProductSearchActivity ปรากฏขึ้นพร้อมกับรูปภาพที่คุณแตะ ปุ่มค้นหายังไม่มีฟังก์ชันการทำงาน แต่เราจะนำไปใช้ในอนาคต

fed40f81b8b43801.png

คุณควรเห็นหน้าจอที่คล้ายกันหลังจากแตะออบเจ็กต์ที่ตรวจพบ

5. สำรวจแบ็กเอนด์ของการค้นหาผลิตภัณฑ์

สร้างแบ็กเอนด์การค้นหารูปภาพผลิตภัณฑ์

Codelab นี้ต้องใช้แบ็กเอนด์การค้นหาผลิตภัณฑ์ที่สร้างด้วย Vision API Product Search โดยมี 2 ตัวเลือก ดังนี้

ตัวเลือกที่ 1: ใช้แบ็กเอนด์เดโมที่ได้รับการติดตั้งใช้งานให้คุณแล้ว

คุณสามารถทำตาม Codelab นี้ได้โดยใช้แบ็กเอนด์การค้นหาผลิตภัณฑ์ที่ Google ได้ติดตั้งใช้งานให้คุณแล้ว คุณสามารถจำลองข้อมูลแบ็กเอนด์ของเดโมได้โดยทำตามคู่มือเริ่มต้นใช้งานการค้นหาผลิตภัณฑ์ด้วย Vision API

ตัวเลือกที่ 2: สร้างแบ็กเอนด์ของคุณเองโดยทำตามการเริ่มต้นใช้งานการค้นหาผลิตภัณฑ์ด้วย Vision API อย่างรวดเร็ว

เราขอแนะนำตัวเลือกนี้สำหรับผู้ที่ต้องการเรียนรู้เชิงลึกเกี่ยวกับวิธีสร้างแบ็กเอนด์การค้นหาผลิตภัณฑ์ เพื่อให้คุณสร้างแบ็กเอนด์สำหรับแคตตาล็อกผลิตภัณฑ์ของคุณเองได้ในภายหลัง คุณจะต้องมีสิ่งต่อไปนี้

  • บัญชี Google Cloud ที่เปิดใช้การเรียกเก็บเงิน (อาจเป็นบัญชีทดลองใช้ฟรีก็ได้)
  • มีความรู้เกี่ยวกับแนวคิดของ Google Cloud บ้าง เช่น โปรเจ็กต์ บัญชีบริการ เป็นต้น

คุณสามารถดูวิธีดำเนินการนี้ได้ในภายหลังในเส้นทางการเรียนรู้

ดูแนวคิดสำคัญ

คุณจะพบแนวคิดเหล่านี้เมื่อโต้ตอบกับแบ็กเอนด์การค้นหาผลิตภัณฑ์

  • ชุดผลิตภัณฑ์: ชุดผลิตภัณฑ์คือคอนเทนเนอร์ที่เรียบง่ายสำหรับกลุ่มผลิตภัณฑ์ แคตตาล็อกผลิตภัณฑ์สามารถแสดงเป็นชุดผลิตภัณฑ์และผลิตภัณฑ์ของชุดผลิตภัณฑ์นั้น
  • ผลิตภัณฑ์: หลังจากสร้างชุดผลิตภัณฑ์แล้ว คุณจะสร้างผลิตภัณฑ์และเพิ่มลงในชุดผลิตภัณฑ์ได้
  • รูปภาพอ้างอิงของผลิตภัณฑ์: รูปภาพที่มีมุมมองต่างๆ ของผลิตภัณฑ์ ระบบจะใช้รูปภาพอ้างอิงเพื่อค้นหาผลิตภัณฑ์ที่มีลักษณะคล้ายกัน
  • ค้นหาผลิตภัณฑ์: เมื่อสร้างชุดผลิตภัณฑ์และระบบจัดทำดัชนีชุดผลิตภัณฑ์แล้ว คุณจะค้นหาชุดผลิตภัณฑ์ได้โดยใช้ Cloud Vision API

ทำความเข้าใจแคตตาล็อกผลิตภัณฑ์ที่กำหนดไว้ล่วงหน้า

แบ็กเอนด์ของเดโมการค้นหาผลิตภัณฑ์ที่ใช้ใน Codelab นี้สร้างขึ้นโดยใช้ Vision API Product Search และแคตตาล็อกผลิตภัณฑ์ที่มีรูปภาพรองเท้าและชุดประมาณ 100 รูป นี่คือรูปภาพบางส่วนจากแคตตาล็อก

4f1a8507b74ab178.png 79a5fc6c829eca77.png 3528c872f813826e.png

ตัวอย่างจากแคตตาล็อกผลิตภัณฑ์ที่กำหนดไว้ล่วงหน้า

เรียกใช้แบ็กเอนด์ของการสาธิตการค้นหาผลิตภัณฑ์

คุณสามารถเรียกใช้การค้นหาผลิตภัณฑ์ของ Vision API ได้โดยตรงจากแอปบนอุปกรณ์เคลื่อนที่โดยการตั้งค่าคีย์ Google Cloud API และจำกัดการเข้าถึงคีย์ API ให้เฉพาะแอปของคุณ

เราได้ตั้งค่าปลายทางพร็อกซีเพื่อให้ Codelab นี้ใช้งานง่าย ซึ่งจะช่วยให้คุณเข้าถึงแบ็กเอนด์ของเดโมได้โดยไม่ต้องกังวลเรื่องคีย์ API และการตรวจสอบสิทธิ์ โดยจะรับคำขอ HTTP จากแอปบนอุปกรณ์เคลื่อนที่ ผนวกคีย์ API และส่งต่อคำขอไปยังแบ็กเอนด์ของ Vision API Product Search จากนั้นพร็อกซีจะได้รับการตอบกลับจากแบ็กเอนด์และส่งกลับไปยังแอปบนอุปกรณ์เคลื่อนที่

ในโค้ดแล็บนี้ คุณจะได้ใช้ API 2 รายการของ 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 เราได้ติดตั้งใช้งานโค้ด Boilerplate บางส่วนให้คุณในแอปเริ่มต้นแล้ว ดังนี้

  • class ProductSearchAPIClient: ตอนนี้คลาสนี้ว่างเปล่าเป็นส่วนใหญ่ แต่มีเมธอดบางอย่างที่คุณจะใช้ในภายหลังใน Codelab นี้
  • fun convertBitmapToBase64(bitmap: Bitmap): แปลงอินสแตนซ์ Bitmap เป็นการแสดง Base64 เพื่อส่งไปยังแบ็กเอนด์การค้นหาผลิตภัณฑ์
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: เรียกใช้ API projects.locations.images.annotate และแยกวิเคราะห์การตอบกลับ
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: เรียกใช้ API projects.locations.products.referenceImages.get และแยกวิเคราะห์การตอบกลับ
  • SearchResult.kt: ไฟล์นี้มีคลาสข้อมูลหลายรายการเพื่อแสดงประเภทที่แบ็กเอนด์การค้นหาผลิตภัณฑ์ของ Vision API ส่งคืน

ระบุการกำหนดค่า API

ไปที่ProductSearchAPIClient class แล้วคุณจะเห็นการกำหนดค่าบางอย่างของแบ็กเอนด์การค้นหาผลิตภัณฑ์ที่กำหนดไว้แล้ว

// 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 คือตำแหน่งในระบบคลาวด์ที่ติดตั้งใช้งานแบ็กเอนด์การค้นหาผลิตภัณฑ์ us-east1 คือที่ที่เราติดตั้งใช้งานแบ็กเอนด์ของเดโม
  • VISION_API_PRODUCT_SET_ID คือรหัสของแคตตาล็อกผลิตภัณฑ์ (หรือที่เรียกว่า "ชุดผลิตภัณฑ์" ในคำศัพท์ของ Vision API) ที่คุณต้องการค้นหาผลิตภัณฑ์ที่คล้ายกันในเชิงภาพ คุณมีแคตตาล็อกหลายรายการในโปรเจ็กต์ Cloud เดียวได้ product_set0 คือแคตตาล็อกผลิตภัณฑ์ที่กำหนดไว้ล่วงหน้าของแบ็กเอนด์เดโม

7. เรียกใช้ API การค้นหาผลิตภัณฑ์

สำรวจรูปแบบคำขอและการตอบกลับของ API

คุณค้นหาผลิตภัณฑ์ที่คล้ายกับรูปภาพที่ต้องการได้โดยส่ง URI ของ Google Cloud Storage, URL ของเว็บ หรือสตริงที่เข้ารหัส Base64 ของรูปภาพไปยังการค้นหาผลิตภัณฑ์ของ Vision API ใน Codelab นี้ คุณจะได้ใช้ตัวเลือกสตริงที่เข้ารหัส base64 เนื่องจากรูปภาพคำค้นหาของเรามีอยู่ในอุปกรณ์ของผู้ใช้เท่านั้น

คุณต้องส่งคำขอ POST ไปยังปลายทาง projects.locations.images.annotate พร้อมเนื้อความของคำขอ JSON นี้

{
  "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: การแสดงฐาน 64 (สตริง ASCII) ของข้อมูลไบนารีของรูปภาพคำค้นหา
  • project-id: รหัสโปรเจ็กต์ GCP
  • location-id: ตัวระบุสถานที่ตั้งที่ถูกต้อง
  • product-set-id: รหัสสำหรับชุดผลิตภัณฑ์ที่คุณต้องการเรียกใช้การดำเนินการ

เนื่องจากแคตตาล็อกผลิตภัณฑ์มีเฉพาะรูปภาพรองเท้าและชุด ให้ระบุ productCategories เป็น apparel-v2 v2 ในที่นี้หมายความว่าเราใช้แมชชีนเลิร์นนิงโมเดลการค้นหาผลิตภัณฑ์เครื่องแต่งกายเวอร์ชัน 2

หากคำขอสำเร็จ เซิร์ฟเวอร์จะแสดงรหัสสถานะ HTTP 200 OK และการตอบกลับในรูปแบบ JSON JSON ของการตอบกลับมีผลลัพธ์ 2 ประเภทต่อไปนี้

  • productSearchResults - มีรายการผลิตภัณฑ์ที่ตรงกันสำหรับทั้งรูปภาพ
  • 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} คุณจะต้องส่งคำขอ API อีกรายการไปยัง projects.locations.products.referenceImages.get เพื่อรับ URL ของรูปภาพอ้างอิงนี้เพื่อให้แสดงบนหน้าจอ
  • product.labels: รายการแท็กที่กำหนดไว้ล่วงหน้าของผลิตภัณฑ์ ซึ่งจะมีประโยชน์หากคุณต้องการกรองผลการค้นหาเพื่อแสดงเฉพาะเสื้อผ้าหมวดหมู่เดียว เช่น ชุดเดรส

แปลงรูปภาพคำค้นหาเป็น Base64

คุณต้องแปลงรูปภาพคำค้นหาเป็นสตริงฐาน 64 และแนบสตริงกับออบเจ็กต์ 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 พร้อมใช้งานแล้ว กลับไปที่กิจกรรม ProductSearchActivity เพื่อใช้โค้ด UI

กิจกรรมมีโค้ดบอยเลอร์เพลตบางส่วนอยู่แล้วซึ่งทริกเกอร์เมธอด 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 เมธอดมีโค้ด Boilerplate บางส่วนที่แยกวิเคราะห์การตอบกลับของ API และแสดงบนหน้าจอให้คุณ

เรียกใช้

ตอนนี้คลิกเรียกใช้ ( 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

คุณจะส่งคำขอ HTTP GET ที่มีเนื้อหาคำขอว่างไปยังปลายทาง 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"
}
  • name: ตัวระบุรูปภาพอ้างอิง
  • uri: URI ของรูปภาพใน Google Cloud Storage (GCS)

เราตั้งค่ารูปภาพอ้างอิงของแบ็กเอนด์การค้นหาผลิตภัณฑ์เดโมให้มีสิทธิ์อ่านแบบสาธารณะ ดังนั้น คุณจึงแปลง URI ของ GCS เป็น URL ของ HTTP และแสดงใน UI ของแอปได้อย่างง่ายดาย คุณเพียงแค่ต้องแทนที่คำนำหน้า 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: ProductSearchResult ซึ่งปลายทางการค้นหาผลิตภัณฑ์ส่งคืนมา จากนั้นทำตามขั้นตอนต่อไปนี้

  1. เรียกใช้ปลายทางของรูปภาพอ้างอิงเพื่อรับ URI ของ GCS ของรูปภาพอ้างอิง
  2. แปลง URI ของ GCS เป็น URL ของ HTTP
  3. อัปเดตพร็อพเพอร์ตี้ httpUri ของออบเจ็กต์ searchResult ด้วย URL ของ HTTP นี้

เชื่อมต่อคำขอ API ทั้ง 2 รายการ

กลับไปที่ annotateImage แล้วแก้ไขเพื่อให้ได้ HTTP URL ของรูปภาพอ้างอิงทั้งหมดก่อนที่จะส่งคืนรายการ 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 ให้คุณแล้ว คุณจึงดำเนินการต่อเพื่อเรียกใช้แอปอีกครั้งได้

เรียกใช้

ตอนนี้คลิกเรียกใช้ ( execute.png) ในแถบเครื่องมือ Android Studio เมื่อแอปโหลดแล้ว ให้แตะรูปภาพที่ตั้งค่าไว้ เลือกออบเจ็กต์ที่ตรวจพบ แล้วแตะปุ่มค้นหาเพื่อดูผลการค้นหา ซึ่งคราวนี้จะมีรูปภาพผลิตภัณฑ์ด้วย

ผลการค้นหาผลิตภัณฑ์มีความสมเหตุสมผลสำหรับคุณไหม

25939f5a13eeb3c3.png

9. ยินดีด้วย

คุณได้เรียนรู้วิธีเรียกใช้แบ็กเอนด์การค้นหาผลิตภัณฑ์ของ Vision API เพื่อเพิ่มความสามารถในการค้นหารูปภาพผลิตภัณฑ์ลงในแอป Android แล้ว เพียงเท่านี้คุณก็พร้อมใช้งานแล้ว

เมื่อดำเนินการต่อ คุณอาจต้องการสร้างแบ็กเอนด์ของคุณเองโดยใช้แคตตาล็อกผลิตภัณฑ์ ดู Codelab ถัดไปในเส้นทางการเรียนรู้การค้นหารูปภาพผลิตภัณฑ์เพื่อดูวิธีสร้างแบ็กเอนด์ของคุณเองและตั้งค่าคีย์ API เพื่อเรียกใช้จากแอปบนอุปกรณ์เคลื่อนที่

สิ่งที่เราได้พูดถึง

  • วิธีเรียกใช้แบ็กเอนด์การค้นหาผลิตภัณฑ์ของ Vision API จากแอป Android

ขั้นตอนถัดไป

ดูข้อมูลเพิ่มเติม