แบ็กเอนด์ Product Vision API ของ Call ใน Android

1. ข้อควรทราบก่อนที่จะเริ่มต้น

bd8c01b2f8013c6d.png

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

ใน 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 Product Search จะใช้แมชชีนเลิร์นนิงในการเปรียบเทียบผลิตภัณฑ์ในชุดคําค้นหาของผู้ใช้กับรูปภาพในชุดผลิตภัณฑ์ของผู้ค้าปลีก จากนั้น จากนั้นแสดงผลการค้นหาที่มีอันดับคล้ายกันและมีความหมาย

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

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

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

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

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

  • android_studio_folder.เงื่อนไขเริ่มต้น - โค้ดเริ่มต้นที่สร้างขึ้นสําหรับ Codelab นี้
  • android_studio_folder.final - โค้ดเสร็จสมบูรณ์สําหรับแอปตัวอย่างที่เสร็จสมบูรณ์

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

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

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

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

7c0f27882a2698ac.png

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

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

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

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

c6102a808fdfcb11.png

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

จากนั้นจะขยายแอปให้ส่งออบเจ็กต์ที่ตรวจพบไปยังแบ็กเอนด์ Vision API Product Search และแสดงผลการค้นหาบนหน้าจอ

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

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

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

9cdfcead6d95a87.png

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

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

  • 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 เมื่อใดก็ตามที่ผู้ใช้แตะวัตถุที่ตรวจพบบนหน้าจอ และจะได้รับรูปภาพที่ครอบตัดซึ่งมีเฉพาะออบเจ็กต์ที่เลือก ตัวอย่างเช่น หากผู้ใช้แตะบุคคลที่สวมชุดเดรสด้านขวา ผู้ฟังก็จะเริ่มทํางานด้วย objectImage ด้านล่าง

9cac8458d0f326e6.png

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

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

ตอนนี้คุณจะใช้ตรรกะในการส่งรูปภาพการค้นหาไปยังแบ็กเอนด์ Vision API ของ Product Search ในกิจกรรมแยกต่างหาก (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 ของ Android Intent ได้
  • คุณสามารถเก็บรูปภาพการค้นหาในรูปแบบ 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))
}

เรียกใช้แอป

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

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

ยืนยันว่า ProductSearchActivity แสดงพร้อมกับรูปภาพที่คุณแตะ ปุ่มค้นหา ยังไม่ได้ทําอะไรเลย แต่เราจะใช้ปุ่มถัดไป

fed40f81b8b43801.png

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

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

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

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

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

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

ตัวเลือกที่ 2: สร้างแบ็กเอนด์ของคุณเองโดยทําตามคู่มือเริ่มใช้งาน Vision API Product Search ฉบับย่อ

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

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

โดยดูวิธีการได้ในภายหลังที่เส้นทางการเรียนรู้

เรียนรู้แนวคิดสําคัญ

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

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

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

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

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

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

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

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

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

ใน Codelab นี้ คุณจะใช้ API 2 รายการของการค้นหาผลิตภัณฑ์ Vision API

  • 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>>: เรียกใช้ 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 ของโปรเจ็กต์ระบบคลาวด์ เนื่องจากพร็อกซีจัดการการตรวจสอบสิทธิ์อยู่แล้ว ให้เว้นว่างไว้
  • VISION_API_PROJECT_ID คือรหัสโปรเจ็กต์ Cloud odml-codelabs คือโปรเจ็กต์ระบบคลาวด์ที่ทําให้แบ็กเอนด์สาธิตใช้งานได้
  • VISION_API_LOCATION_ID คือตําแหน่งระบบคลาวด์ที่ทําให้แบ็กเอนด์การค้นหาผลิตภัณฑ์ใช้งานได้ us-east1 คือตําแหน่งที่เราใช้ทําให้แบ็กเอนด์สาธิตใช้งานได้
  • VISION_API_PRODUCT_SET_ID คือรหัสของแคตตาล็อกผลิตภัณฑ์ (หรือที่เรียกว่า "product set" ในข้อกําหนดของ Vision API) ที่คุณต้องการค้นหาผลิตภัณฑ์ที่ดูคล้ายกัน คุณมีแคตตาล็อกหลายรายการในโปรเจ็กต์ระบบคลาวด์เดียวได้ 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-encrypted-image: การนําเสนอฐาน 64 (สตริง ASCII) ของข้อมูลไบนารีของรูปภาพ&#39
  • project-id: รหัสโปรเจ็กต์ GCP
  • รหัสสถานที่ตั้ง [location-id]: ตัวระบุสถานที่ตั้งที่ถูกต้อง
  • product-set-id: รหัสของชุดผลิตภัณฑ์ที่คุณต้องการเรียกใช้

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

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

กิจกรรมนี้มีโค้ด Boilerplate ที่เรียกใช้เมธอด 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 และแสดงบนหน้าจอให้คุณ

เรียกใช้

จากนั้นคลิกเรียกใช้ (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"
}
  • ชื่อ: ตัวระบุรูปภาพอ้างอิง
  • 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 เป็น HTTP URL
  3. อัปเดตพร็อพเพอร์ตี้ httpUri ของออบเจ็กต์ searchResult ด้วย HTTP URL นี้

เชื่อมต่อคําขอ 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) }

โค้ด Boilerplate ที่ใช้แสดงรูปภาพอ้างอิงบนหน้าจอได้รับการติดตั้งใช้งานแล้วในคลาส ProductSearchAdapter ให้คุณดําเนินการต่อแล้วคุณสามารถเรียกใช้แอปอีกครั้ง

เรียกใช้

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

ผลการค้นหาผลิตภัณฑ์เหมาะกับคุณหรือไม่

25939f5a13eeb3c3.png

9. ยินดีด้วย

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

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

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

  • วิธีเรียกแบ็กเอนด์ Vision API Product Search จากแอป Android

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

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