1. ข้อควรทราบก่อนที่จะเริ่มต้น
ใน Codelab นี้ คุณจะได้สํารวจวิธีสร้างแอปที่จัดการกับกรณีการใช้งานหลักของ Computer Vision ซึ่งตรวจจับเนื้อหาหลักของรูปภาพ ซึ่งมักเรียกว่าการจัดประเภทรูปภาพหรือการติดป้ายกํากับรูปภาพ
สิ่งที่ต้องมีก่อน
Codelab นี้เป็นส่วนหนึ่งของเส้นทางเริ่มต้นใช้งานการแยกประเภทรูปภาพ ซึ่งเขียนขึ้นสําหรับนักพัฒนาซอฟต์แวร์ที่มีประสบการณ์และเพิ่งเริ่มใช้แมชชีนเลิร์นนิง
สิ่งที่คุณจะสร้าง
- แอป Android จัดประเภทรูปภาพดอกไม้ได้
- (ไม่บังคับ) แอป iOS ที่จัดประเภทรูปภาพดอกไม้ได้
สิ่งที่ต้องมี
- Android Studio พร้อมใช้งานแล้วที่ https://developer.android.com/studio สําหรับส่วน Android ของ Codelab
- Xcode ที่มีอยู่ใน Apple App Store สําหรับ iOS ของ Codelab
2. เริ่มต้น
คอมพิวเตอร์วิทัศน์เป็นสาขาที่มากขึ้นในสาขาแมชชีนเลิร์นนิงซึ่งทํางานเพื่อหาวิธีใหม่ๆ ให้คอมพิวเตอร์ประมวลผลและแยกข้อมูลจากเนื้อหาของรูปภาพ ในกรณีที่คอมพิวเตอร์จะจัดเก็บเฉพาะข้อมูลจริงของรูปภาพ เช่น ค่าพิกเซลที่ทําให้เกิดรูปภาพ คอมพิวเตอร์วิทัศน์ช่วยให้คอมพิวเตอร์แยกวิเคราะห์เนื้อหาของรูปภาพและข้อมูลเกี่ยวกับสิ่งที่อยู่ในรูปภาพได้
เช่น ภายในช่อง Vision คอมพิวเตอร์ รูปภาพแมวอาจติดป้ายกํากับว่ามีแมว นอกเหนือจากพิกเซลที่ประกอบขึ้นเป็นรูปภาพดังกล่าว มีช่องสําหรับคอมพิวเตอร์วิทัศน์ที่มีรายละเอียดอีกมากมาย เช่น การตรวจจับวัตถุ ซึ่งคอมพิวเตอร์จะค้นหารายการต่างๆ ได้จากรูปภาพและกล่องล้อมรอบ
ใน Codelab นี้ คุณจะได้สํารวจวิธีสร้างแอปที่จัดการกับ Use Case หลัก เพื่อตรวจหาเนื้อหาหลักของรูปภาพ ซึ่งมักเรียกว่าการจัดประเภทรูปภาพหรือการติดป้ายกํากับรูปภาพ
แอปจะใช้รูปภาพที่รวมอยู่ในแพ็กเกจเป็นทรัพยากรและแสดงการแยกประเภทแอปเพื่อให้เรียบง่ายที่สุด ส่วนขยายในอนาคตอาจใช้เครื่องมือเลือกรูปภาพหรือดึงรูปภาพโดยตรงจากกล้อง
คุณจะเริ่มต้นจากขั้นตอนการสร้างแอปบน Android โดยใช้ Android Studio (ข้ามไปยังขั้นตอนที่ 7 เพื่อที่เทียบเท่ากันใน iOS)
- เปิด Android Studio ไปที่เมนู "ไฟล์" แล้วเลือก "สร้างโปรเจ็กต์ใหม่"
- ระบบจะขอให้คุณเลือกเทมเพลตโครงการ เลือก "กิจกรรมเปล่า"
- คลิกถัดไป ระบบจะขอให้กําหนดค่าโปรเจ็กต์ ตั้งชื่อและชื่อแพ็กเกจที่ต้องการ แต่โค้ดตัวอย่างใน Codelab นี้ใช้ชื่อโปรเจ็กต์ ImageClassifierStep1 และชื่อแพ็กเกจ com.google.imageclassifierstep1
- เลือกภาษาที่ต้องการ ไม่ว่าจะเป็น Kotlin หรือ Java ห้องทดลองนี้ใช้ Kotlin ดังนั้นหากคุณต้องการติดตามไปพร้อมๆ กัน คุณอาจต้องเลือก Kotlin
- เมื่อพร้อมแล้ว คลิกเสร็จสิ้น Android Studio จะสร้างแอปให้คุณ อาจต้องใช้เวลาสักครู่เพื่อตั้งค่าทุกอย่าง
3. นําเข้าไลบรารีป้ายกํากับรูปภาพของ ML Kit'
ML Kit (https://developers.google.com/ml-kit) มีโซลูชันมากมายสําหรับนักพัฒนาซอฟต์แวร์ ตรงตามสถานการณ์ที่พบบ่อยในแมชชีนเลิร์นนิงและช่วยให้นําไปใช้งานข้ามแพลตฟอร์มได้ง่าย ML Kit มีไลบรารีครบวงจรที่คุณสามารถใช้ในแอปนี้โดยใช้การติดป้ายกํากับรูปภาพ ไลบรารีนี้มีโมเดลที่ผ่านการฝึกล่วงหน้าให้จดจํารูปภาพกว่า 600 คลาส ดังนั้น การเริ่มต้นใช้งานจึงดีมาก
โปรดทราบว่า ML Kit ยังอนุญาตให้คุณใช้โมเดลที่กําหนดเองโดยใช้ API เดียวกัน ดังนั้นเมื่อคุณพร้อมแล้ว คุณสามารถก้าวไปไกลกว่า "เริ่มต้นใช้งาน" และเริ่มสร้างแอปติดป้ายกํากับรูปภาพที่ปรับเปลี่ยนในแบบของคุณซึ่งใช้โมเดลที่ฝึกสําหรับสถานการณ์ของคุณ
ในสถานการณ์เช่นนี้ คุณจะสร้างการจดจําดอกไม้ได้ เมื่อคุณสร้างแอปแรกและแสดงรูปดอกไม้ แอปจะจดจําว่าเป็นดอกไม้ (หลังจากนั้น เมื่อคุณสร้างโมเดลตัวตรวจจับดอกไม้ของคุณเอง คุณจะวางแอปนั้นลงในแอปได้โดยแทบไม่มีการเปลี่ยนแปลงด้วย ML Kit และให้โมเดลใหม่บอกว่าเป็นดอกไม้ประเภทใด เช่น ทิวลิปหรือกุหลาบ)
- ใน Android Studio โดยใช้เครื่องมือสํารวจโปรเจ็กต์ ให้ตรวจสอบว่าเลือก Android ที่ด้านบน
- เปิดโฟลเดอร์ Gradle Scripts แล้วเลือกไฟล์
build.gradle
ให้กับแอป ซึ่งอาจมีไฟล์อย่างน้อย 2 ไฟล์ ดังนั้นโปรดใช้ระดับแอปตามที่ปรากฏที่นี่
- ที่ด้านล่างของไฟล์ คุณจะเห็นส่วนที่เรียกว่าการขึ้นต่อกันที่จัดเก็บการตั้งค่า
implementation
,testImplementation
และandroidImplementation
เพิ่มโค้ดใหม่ในไฟล์ที่มีโค้ดนี้
implementation 'com.google.mlkit:image-labeling:17.0.3'
(ตรวจสอบว่าการดําเนินการนี้อยู่ในทรัพยากร Dependency { })
- คุณจะเห็นแถบปรากฏขึ้นที่ด้านบนของหน้าต่างแจ้งว่า
build.gradle
มีการเปลี่ยนแปลง และคุณจะต้องซิงค์ใหม่ ทําตามนี้ได้เลย หากคุณไม่เห็นไอคอนดังกล่าว ให้มองหาไอคอนช้างขนาดเล็กในแถบเครื่องมือที่ด้านบนขวา แล้วคลิกไอคอนนั้น
ตอนนี้คุณนําเข้า ML Kit แล้ว และคุณพร้อมที่จะเริ่มการติดป้ายกํากับรูปภาพแล้ว
ขั้นต่อไป คุณจะต้องสร้างอินเทอร์เฟซผู้ใช้ที่เรียบง่ายเพื่อแสดงผลรูปภาพ และให้ปุ่มเมื่อผู้ใช้กดให้ ML Kit เรียกใช้โมเดลป้ายกํากับรูปภาพเพื่อแยกวิเคราะห์เนื้อหาของรูปภาพ
4. สร้างอินเทอร์เฟซผู้ใช้
ใน Android Studio คุณแก้ไขอินเทอร์เฟซผู้ใช้สําหรับแต่ละหน้าจอ (หรือกิจกรรม) ได้โดยใช้ไฟล์เลย์เอาต์แบบ xml แอปพื้นฐานที่คุณสร้างมีกิจกรรมเดียว (ซึ่งมีรหัสอยู่ใน MainActivity
และคุณจะเห็นเร็วๆ นี้) และการประกาศอินเทอร์เฟซผู้ใช้อยู่ใน activity_main.xml
คุณจะพบการอัปเดตนี้ได้ในโฟลเดอร์ res >Layout ใน Project Explorer ของ Android ดังนี้
การดําเนินการนี้จะเปิดเครื่องมือแก้ไขเต็มรูปแบบที่ช่วยให้คุณออกแบบอินเทอร์เฟซผู้ใช้ของกิจกรรมได้ ที่นั่นมีขั้นตอนมากมาย และไม่ได้มีจุดประสงค์ให้ห้องทดลองนี้สอนวิธีใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับเครื่องมือแก้ไขเลย์เอาต์ได้ที่ https://developer.android.com/studio/write/layout-editor
สําหรับห้องทดลองนี้ ให้เลือกเครื่องมือโค้ดที่มุมขวาบนของตัวแก้ไข
ตอนนี้คุณจะเห็นเพียงโค้ด XML ในส่วนหลักของหน้าต่าง เปลี่ยนโค้ดให้เป็นดังนี้
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/imageToLabel"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/btnTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Label Image"
android:layout_gravity="center"/>
<TextView
android:id="@+id/txtOutput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:gravity="start|top" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
วิธีนี้จะสร้างเลย์เอาต์ที่เรียบง่ายที่สุดที่มี ImageView
(เพื่อแสดงผลรูปภาพ) Button
(ให้ผู้ใช้กด) และ TextView
ที่จะแสดงป้ายกํากับ
ตอนนี้คุณก็ได้กําหนดอินเทอร์เฟซผู้ใช้แล้ว ก่อนเขียนโค้ด ให้เพิ่มรูปภาพบางส่วนเป็นเนื้อหา แล้วแอปจะอนุมานรูปภาพเหล่านี้
5. รวมรูปภาพด้วยแอป
วิธีหนึ่งในการรวมไฟล์เพิ่มเติมด้วยแอป Android คือการเพิ่มไฟล์เป็นเนื้อหาที่รวบรวมไว้ในแอป โดยเราจะแอปนี้ทําเพื่อเพิ่มรูปภาพดอกไม้บางส่วนเพื่อให้แอปนี้เรียบง่าย หลังจากนั้น คุณจะขยายแอปนี้ไปใช้ CameraX หรือไลบรารีอื่นๆ เพื่อถ่ายภาพและใช้ได้ แต่เพื่อความเรียบง่าย เราจะรวมรูปภาพไว้ในตอนนี้
- ใน Project Explorer ให้คลิกเลือกไดเรกทอรีใหม่ทางด้านขวาบน
- ในกล่องโต้ตอบที่ปรากฏพร้อมรายชื่อไดเรกทอรีที่แตกต่างกัน ให้เลือก src/main/assets
เมื่อทําเช่นนี้แล้ว คุณจะเห็นโฟลเดอร์ assets ใหม่ปรากฏในตัวสํารวจโปรเจ็กต์ ดังนี้
- คลิกขวาที่โฟลเดอร์นี้ จากนั้นคุณจะเห็นป๊อปอัปที่มีรายการตัวเลือก โฟลเดอร์ใดโฟลเดอร์หนึ่งต่อไปนี้จะเปิดโฟลเดอร์ในระบบไฟล์ หาส่วนขยายที่เหมาะสมสําหรับระบบปฏิบัติการของคุณ แล้วเลือกส่วนขยายดังกล่าว (สําหรับเครื่อง Mac จะเป็นแสดงใน Finder สําหรับ Windows จะเป็น Open in Explorer และใน Ubuntu จะเป็น Show in Files)
- คัดลอกไฟล์ลงในไฟล์ คุณสามารถดาวน์โหลดรูปภาพจากเว็บไซต์อย่างเช่น Pixabay ขอแนะนําให้เปลี่ยนชื่อรูปภาพที่เรียบง่าย ในกรณีนี้ รูปภาพได้เปลี่ยนชื่อเป็น
flower1.jpg
เมื่อเสร็จแล้ว ให้กลับไปที่ Android Studio แล้วคุณจะเห็นไฟล์ในโฟลเดอร์เนื้อหา
ตอนนี้คุณพร้อมจะติดป้ายกํากับรูปภาพนี้แล้ว
6. เขียนรหัสการแยกประเภทเพื่อติดป้ายกํากับรูปภาพ
(และตอนนี้ส่วนที่เราทุกคนรอคอย ก็ทํา Computer Vision บน Android)
- คุณจะเขียนโค้ดในไฟล์
MainActivity
ดังนั้นให้ค้นหาในโฟลเดอร์โครงการในส่วน com.google.devrel.imageclassifierstep1 (หรือเนมสเปซที่เทียบเท่ากันหากเลือกไว้) โปรดทราบว่าโดยปกติแล้วจะมีโฟลเดอร์เนมสเปซกําหนดไว้ 3 รายการในโปรเจ็กต์ Android Studio โฟลเดอร์หนึ่งสําหรับแอป โฟลเดอร์หนึ่งสําหรับการทดสอบ Android และโฟลเดอร์สําหรับการทดสอบ คุณจะเห็นMainActivity
ใน URL ที่ไม่มีคําอธิบายในวงเล็บปีกกา
หากเลือกใช้ Kotlin คุณอาจสงสัยว่าทําไมโฟลเดอร์ระดับบนสุดจึงมีชื่อว่า Java ถือเป็นโบราณวัตถุอันเก่าแก่ในสมัยที่ Android Studio เป็น Java เท่านั้น เวอร์ชันในอนาคตอาจแก้ไขปัญหานี้ได้ แต่ไม่ต้องกังวล หากต้องการใช้ Kotlin คุณก็ไม่เป็นไร แต่เป็นเพียงชื่อโฟลเดอร์สําหรับซอร์สโค้ด
- เปิดไฟล์
MainActivity
แล้วคุณจะเห็นไฟล์คลาสที่ชื่อว่า MainActivity ในตัวแก้ไขโค้ด ซึ่งควรมีลักษณะดังนี้
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
ใต้วงเล็บปีกกาปิดอยู่ คุณสามารถเพิ่มโค้ดส่วนขยายที่ไม่ได้เป็นส่วนหนึ่งของชั้นเรียน แต่จะใช้ได้โดยชั้นเรียนเท่านั้น คุณจะต้องใช้ส่วนขยายเพื่ออ่านไฟล์จากเนื้อหาเป็นบิตแมป ซึ่งจะใช้ในการโหลดรูปภาพที่คุณคัดลอกไปยังโฟลเดอร์ชิ้นงานไว้ก่อนหน้านี้
- เพิ่มโค้ดนี้:
// extension function to get bitmap from assets
fun Context.assetsToBitmap(fileName: String): Bitmap?{
return try {
with(assets.open(fileName)){
BitmapFactory.decodeStream(this)
}
} catch (e: IOException) { null }
}
ขณะนี้ Android Studio อาจร้องเรียนและไฮไลต์โค้ดบางส่วนเป็นสีแดง เช่น Context
, Bitmap
และ IOException
ไม่ต้องกังวล เนื่องจากคุณยังไม่ได้นําเข้าไลบรารีที่มีไลบรารีดังกล่าว Android Studio มีทางลัดที่มีประโยชน์
- ลากเคอร์เซอร์เหนือคํา แล้วกด ALT + Enter (Option + Enter ใน Mac) ระบบจะสร้างการนําเข้าให้
- จากนั้นคุณจะสามารถโหลดบิตแมปจากเนื้อหาและวางใน ImageView ได้ กลับไปที่
onCreateFunction
ของ MainActivity ให้เพิ่มโค้ดนี้ใต้บรรทัดsetContentView
val img: ImageView = findViewById(R.id.imageToLabel)
// assets folder image file name with extension
val fileName = "flower1.jpg"
// get bitmap from assets folder
val bitmap: Bitmap? = assetsToBitmap(fileName)
bitmap?.apply {
img.setImageBitmap(this)
}
- และก่อนหน้านี้ ระบบจะไฮไลต์โค้ดบางส่วนเป็นสีแดง วางเคอร์เซอร์ในบรรทัดนั้นแล้วใช้ Alt + Enter / Option + Enter เพื่อเพิ่มการนําเข้าโดยอัตโนมัติ
- ในไฟล์
layout.xml
ที่คุณสร้างไว้ก่อนหน้านี้ คุณได้ตั้งชื่อว่า"ViewImage"เป็นบรรทัดแรก ดังนั้นบรรทัดแรกจะสร้างอินสแตนซ์ของออบเจ็กต์ ImageView ซึ่งเรียกว่า img โดยใช้ข้อมูลเลย์เอาต์นั้น โดยจะดูรายละเอียดโดยใช้findViewById
ซึ่งเป็นฟังก์ชัน Android ในตัว จากนั้นจะใช้ชื่อไฟล์flower1.jpg
เพื่อโหลดรูปภาพจากโฟลเดอร์เนื้อหาโดยใช้ฟังก์ชันassetsToBitmap
ที่คุณสร้างในขั้นตอนก่อนหน้า และสุดท้าย ใช้คลาสนามธรรมบิตแมปเพื่อโหลดบิตแมปลงใน img - ไฟล์เลย์เอาต์มี TextView ที่จะใช้ในการแสดงผลป้ายกํากับที่ระบบอนุมานสําหรับรูปภาพ รับออบเจ็กต์โค้ดสําหรับรายการถัดไป เพิ่มโค้ดต่อไปนี้ใต้โค้ดก่อนหน้า
val txtOutput : TextView = findViewById(R.id.txtOutput)
ก่อนหน้านี้ ข้อมูลไฟล์เลย์เอาต์จะปรากฏสําหรับมุมมองข้อความที่ใช้ชื่อ (ตรวจสอบ XML ที่ชื่อ txtOutput
) แล้วใช้เรียกออบเจ็กต์ TextView ชื่อ txtเอาต์พุต
ในทํานองเดียวกัน คุณจะต้องสร้างออบเจ็กต์ปุ่มเพื่อใช้แทนปุ่มดังกล่าว และสร้างอินสแตนซ์ด้วยเนื้อหาของไฟล์เลย์เอาต์
ในไฟล์เลย์เอาต์เรียกว่าปุ่ม btnTest
เพื่อให้เราสามารถสร้างอินสแตนซ์ได้ทันที ดังนี้
val btn: Button = findViewById(R.id.btnTest)
เมื่อเริ่มต้นการเขียนโค้ดและตัวควบคุมทั้งหมดแล้ว ขั้นตอนถัดไป (และขั้นตอนสุดท้าย) ก็คือการใช้เครื่องมือและอนุมานรูปภาพ
ก่อนดําเนินการต่อ โปรดตรวจสอบว่ารหัส onCreate
มีลักษณะดังนี้
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val img: ImageView = findViewById(R.id.imageToLabel)
// assets folder image file name with extension
val fileName = "flower1.jpg"
// get bitmap from assets folder
val bitmap: Bitmap? = assetsToBitmap(fileName)
bitmap?.apply {
img.setImageBitmap(this)
}
val txtOutput : TextView = findViewById(R.id.txtOutput)
val btn: Button = findViewById(R.id.btnTest)
}
คีย์เวิร์ดทั้งหมดไม่ควรมีสีแดงซึ่งบ่งชี้ว่าคีย์เวิร์ดเหล่านี้ยังไม่ได้นําเข้า หากใช่ โปรดย้อนกลับและทําตามเคล็ดลับ ALT + Enter เพื่อสร้างการนําเข้า
เมื่อใช้ผู้ติดป้ายกํากับรูปภาพ ML Kit' ขั้นตอนแรกมักจะสร้างออบเจ็กต์ตัวเลือกเพื่อปรับแต่งการทํางาน คุณจะแปลงรูปภาพเป็นรูปแบบ InputImage ที่ ML Kit จดจําได้ จากนั้นจึงสร้างออบเจ็กต์ Labeler เพื่ออนุมาน โดยจะแสดงผลลัพธ์แบบไม่พร้อมกันเพื่อให้คุณแยกวิเคราะห์ได้
บนปุ่มที่เพิ่งสร้าง ให้ทําทุกอย่างภายในกิจกรรม onClickListener
ของปุ่มนั้น นี่คือรหัสที่สมบูรณ์
btn.setOnClickListener {
val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS)
val image = InputImage.fromBitmap(bitmap!!, 0)
var outputText = ""
labeler.process(image)
.addOnSuccessListener { labels ->
// Task completed successfully
for (label in labels) {
val text = label.text
val confidence = label.confidence
outputText += "$text : $confidence\n"
}
txtOutput.text = outputText
}
.addOnFailureListener { e ->
// Task failed with an exception
}
}
- เมื่อผู้ใช้คลิกปุ่มเป็นครั้งแรก โค้ดจะเป็นการแสดงตัวอย่างป้ายกํากับโดยใช้ ImageLabeling.getClient โดยจะส่ง ImageLabelerOptions ไปยังป้ายกํากับ โดยมาพร้อมกับพร็อพเพอร์ตี้ DEFAULT_OPTIONS ที่ช่วยให้เราเริ่มต้นใช้งานได้อย่างรวดเร็ว
- ถัดไป ระบบจะสร้าง InputImage จากบิตแมปโดยใช้เมธอด fromBitmap InputImage เป็นรูปแบบที่ต้องการสําหรับการประมวลผลรูปภาพด้วย ML Kit'
- สุดท้ายผู้ติดป้ายกํากับจะประมวลผลรูปภาพและโค้ดเรียกกลับแบบไม่พร้อมกัน ไม่ว่าจะสําเร็จหรือไม่สําเร็จ หากการอนุมานสําเร็จ โค้ดเรียกกลับจะรวมรายการป้ายกํากับไว้ด้วย คุณสามารถแยกวิเคราะห์รายการป้ายกํากับนี้เพื่ออ่านข้อความของป้ายกํากับและค่าความเชื่อมั่นได้ หากไม่สําเร็จ ระบบจะส่งข้อยกเว้นให้คุณกลับมาเพื่อใช้ในการรายงานผู้ใช้
เพียงเท่านี้ก็เรียบร้อยแล้ว ตอนนี้คุณเรียกใช้แอปในอุปกรณ์ Android หรือภายในโปรแกรมจําลองได้แล้ว หากยังไม่เคยทํา ดูวิธีการได้ที่ https://developer.android.com/studio/run/emulator
แอปที่ทํางานในโปรแกรมจําลองมีดังนี้ ในตอนแรก คุณจะเห็นรูปภาพและปุ่ม และป้ายกํากับจะว่างเปล่า
กดปุ่มดังกล่าว แล้วคุณจะได้รับชุดป้ายกํากับสําหรับรูปภาพ
จากตรงนี้คุณจะเห็นว่าผู้ติดป้ายกํากับแสดงให้เห็นว่ามีแนวโน้มสูงที่รูปภาพมีกลีบดอก ดอกไม้ ต้นไม้ และท้องฟ้า ทั้งหมดนี้ล้วนเป็นสิ่งที่ทุกคนกําลังแสดงให้เห็นว่าโมเดลกําลังพยายามแยกวิเคราะห์รูปภาพ
แต่จะระบุไม่ได้ว่านี่เป็นภาพเดซี่ สําหรับกรณีนี้ คุณจะต้องมีรูปแบบที่กําหนดเองที่ผ่านการฝึกเกี่ยวกับดอกไม้ที่เฉพาะเจาะจง และดูวิธีใช้งานในห้องทดลองถัดไป
ในขั้นตอนต่อไป คุณจะได้สํารวจวิธีสร้างแอปเดียวกันนี้บน iOS
7. สร้างตัวแยกประเภทรูปภาพใน iOS - เริ่มต้นใช้งาน
คุณสร้างแอปที่คล้ายกันใน iOS ได้โดยใช้ Xcode
- เปิด Xcode และจากเมนูไฟล์ ให้เลือกโปรเจ็กต์ใหม่ 'คุณจะเห็นกล่องโต้ตอบนี้:
- เลือกแอปตามที่แสดง แล้วคลิกถัดไป ระบบจะขอให้เลือกตัวเลือกสําหรับโครงการ ตั้งชื่อและตัวระบุองค์กรตามที่แสดง ตรวจสอบว่าประเภทอินเทอร์เฟซเป็น Storyboard และภาษาเป็น Swift ตามที่แสดง
- หากต้องการตั้งค่าให้โทรศัพท์ใช้งานได้และตั้งค่าโปรไฟล์นักพัฒนาซอฟต์แวร์ คุณจะตั้งค่าทีมได้ หากไม่มี ให้ปล่อยทิ้งไว้ในไม่มี แล้วคุณจะใช้เครื่องจําลอง iOS เพื่อเรียกใช้แอปได้
- คลิกถัดไป และเลือกโฟลเดอร์เพื่อจัดเก็บโปรเจ็กต์และเก็บไฟล์ไว้ จําตําแหน่งของโปรเจ็กต์นี้ คุณจะต้องใช้ในขั้นตอนถัดไป
- ปิด Xcode ในตอนนี้ เนื่องจากคุณจะเปิดขึ้นมาใหม่โดยใช้ไฟล์พื้นที่ทํางานอื่นหลังจากขั้นตอนถัดไป
8. ผสานรวม ML Kit โดยใช้ Cocoapods
เนื่องจาก ML Kit ใช้งานได้ใน iOS ด้วย คุณจึงสร้างตัวแยกประเภทรูปภาพได้ในลักษณะเดียวกัน คุณจะต้องผสานรวม CocoaPods เพื่อผสานรวม หากคุณยังไม่ได้ติดตั้ง คุณสามารถทําได้ที่ https://cocoapods.org/
- เปิดไดเรกทอรีที่คุณสร้างโปรเจ็กต์ ซึ่งควรมีไฟล์ .xcode○ ของคุณ
ที่นี่คุณจะเห็นไฟล์ .xcode○ ที่ระบุว่า I'm ในตําแหน่งที่ถูกต้อง
- ในโฟลเดอร์นี้ ให้สร้างไฟล์ใหม่ชื่อ Podfile ไม่มีส่วนขยาย ไม่มีส่วนขยาย แต่มีเพียง Podfile เท่านั้น เพิ่มข้อมูลต่อไปนี้
platform :ios, '10.0' target 'ImageClassifierStep1' do pod 'GoogleMLKit/ImageLabeling' end
- บันทึกและกลับไปที่เครื่องชําระเงิน อยู่ในไดเรกทอรีประเภทเดียวกัน
pod install
Cocoapods จะดาวน์โหลดไลบรารีและทรัพยากร Dependency ที่เหมาะสม แล้วสร้างพื้นที่ทํางานใหม่ที่รวมโปรเจ็กต์ของคุณกับทรัพยากร Dependency ภายนอก
โปรดทราบว่าในตอนท้าย ระบบขอให้คุณปิดเซสชัน Xcode และใช้ไฟล์พื้นที่ทํางานนับจากนี้ไป เปิดไฟล์นี้ จากนั้น Xcode จะเปิดขึ้นด้วยโปรเจ็กต์ต้นฉบับและทรัพยากร Dependency ภายนอก
ขณะนี้คุณพร้อมที่จะไปยังขั้นตอนถัดไปและสร้างอินเทอร์เฟซผู้ใช้แล้ว
9. สร้าง UI ของ iOS โดยใช้สตอรีบอร์ด
- เปิดไฟล์
Main.storyboard
แล้วคุณจะเห็นเลย์เอาต์ของอินเทอร์เฟซผู้ใช้พร้อมพื้นที่ออกแบบสําหรับโทรศัพท์ - ที่ด้านขวาบนของหน้าจอคือปุ่ม + ที่คุณสามารถใช้เพื่อเพิ่มการควบคุมได้ คลิกไอคอนเพื่อรับพาเล็ตการควบคุม
- ลากและวางไฟล์ ImageView, Button และ Label ลงในพื้นที่ออกแบบ จัดเรียงจากบนลงล่าง ดังนี้
- ดับเบิลคลิกที่ปุ่มเพื่อแก้ไขข้อความจากปุ่มเป็นแยกประเภท
- ลากแฮนเดิลตัวควบคุมรอบป้ายกํากับเพื่อขยายใหญ่ (สมมติว่าความกว้างเท่ากับ UIImageView และความสูง 2 เท่า)
- เมื่อเลือกป้ายกํากับแล้ว ให้คลิกปุ่มตัวเลือกที่ด้านขวาบนเพื่อแสดงชุดสีเครื่องมือตรวจสอบ
- เมื่อทําเสร็จแล้ว ให้ค้นหาการตั้งค่า Lines และตรวจสอบว่ามีการตั้งค่าเป็น 0 ช่วยให้ป้ายกํากับแสดงจํานวนบรรทัดแบบไดนามิกได้
ตอนนี้คุณพร้อมจะดําเนินการต่อแล้ว ซึ่งก็คือการ UI แบบเขียนโค้ดเพื่อใช้เต้ารับและการทํางาน
10. สร้างการดําเนินการและเต้าเสียบ
เมื่อพัฒนา iOS โดยใช้สตอรีบอร์ด คุณจะอ้างอิงข้อมูลเลย์เอาต์สําหรับการควบคุมโดยใช้เต้ารับ และกําหนดโค้ดเพื่อเรียกใช้เมื่อผู้ใช้ดําเนินการควบคุมโดยใช้การดําเนินการต่างๆ
ในขั้นตอนถัดไป คุณจะต้องสร้างเต้ารับสําหรับ ImageView และป้ายกํากับ URL ของรูปภาพจะอ้างอิงเพื่อโหลดรูปภาพ ป้ายกํากับจะได้รับการอ้างถึงในโค้ดเพื่อตั้งค่าข้อความตามการอนุมานที่มาถึงจาก ML Kit
- ปิดเครื่องมือตรวจสอบด้วยการคลิกที่ตัวควบคุมที่ด้านขวาบนของหน้าจอ แล้วคลิกปุ่มเพิ่มเครื่องมือแก้ไขทางด้านขวาที่อยู่ใต้ตัวควบคุม
- คุณจะมีเลย์เอาต์หน้าจอที่เกิดความสับสนซึ่งเปิด theboard.storyboard 2 ครั้ง ทางด้านซ้าย ในการนําทางโครงการ ให้เลือก ViewController.swift เพื่อให้โค้ดของ View View เปิดขึ้น แพลตฟอร์มการออกแบบอาจหายไปจากตัวแก้ไขสตอรีบอร์ดทางด้านซ้าย แต่ไม่ต้องกังวลไป เซ็นเซอร์อาจยังอยู่เหมือนเดิม
- หากต้องการคืนค่า ให้คลิก View Controller ในมุมมอง View Controller ลองทําให้ UI มีลักษณะเช่นนี้ ด้วยสตอรีบอร์ดทางด้านซ้ายที่แสดงรูปแบบของคุณ และโค้ดสําหรับ ViewController.swift ทางด้านขวา
- เลือก UIImageView จากพื้นที่ออกแบบทางด้านซ้าย แล้วกดปุ่ม Control แล้วลากไปยังตําแหน่งโค้ดทางด้านขวา จากนั้นวางใต้คีย์เวิร์ด
class
(ที่บรรทัด 11 ในภาพหน้าจอด้านบน)
คุณจะเห็นลูกศรเมื่อคุณลาก และเมื่อคุณวางลิงก์ลง คุณจะเห็นป๊อปอัปลักษณะนี้
- กรอกข้อมูลในช่องชื่อเป็น "imageView" แล้วคลิกเชื่อมต่อ
- ทําขั้นตอนนี้ซ้ําร่วมกับป้ายกํากับ แล้วตั้งชื่อ "lbloutput."
- สําคัญ: สําหรับปุ่ม คุณจะทําสิ่งต่อไปนี้ได้เหมือนกัน แต่อย่าลืมตั้งค่าประเภทการเชื่อมต่อเป็นการดําเนินการ ไม่ใช่เต้าเสียบ
- ตั้งชื่อ "doClassification" แล้วคลิกเชื่อมต่อ
เมื่อคุณทําโค้ดเสร็จแล้ว โค้ดควรมีลักษณะดังนี้ (โปรดทราบว่าป้ายกํากับและมุมมองรูปภาพจะประกาศเป็น IBOutlet (Interface Builder Outlet) และปุ่มเป็น IBAction (Interface Builder Action)
import UIKit
class ViewController: UIViewController {
@IBAction func doClassification(_ sender: Any) {
}
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var lblOutput: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
- สุดท้าย ให้จัดกลุ่มรูปภาพด้วยแอปเพื่อให้เราจัดประเภทได้โดยง่าย โดยการลากไฟล์จากเครื่องมือสํารวจไฟล์ไปยังโปรแกรมสํารวจทางด้านซ้ายของ Xcode หากวาง คุณจะเห็นป๊อปอัปแบบนี้
- เลือกช่องทําเครื่องหมายในส่วนเพิ่มลงในเป้าหมายตามที่แสดง แล้วคลิกเสร็จสิ้น
ไฟล์จะมาพร้อมกับแอปและคุณจะจัดประเภทไฟล์ได้อย่างง่ายดาย ตอนนี้คุณก็พร้อมที่จะเขียนโค้ดในอินเทอร์เฟซผู้ใช้เพื่อทําการแยกประเภทรูปภาพแล้ว
11. เขียนโค้ดสําหรับการแยกประเภทรูปภาพ
หลังจากที่ได้ตั้งค่าทุกอย่างเรียบร้อยแล้ว การเขียนโค้ดเพื่อดําเนินการแยกประเภทรูปภาพก็เป็นวิธีที่ง่ายมาก
- เริ่มต้นด้วยการปิดนักออกแบบสตอรีบอร์ดโดยคลิก X ที่มุมซ้ายบนเหนือการออกแบบ ซึ่งจะช่วยให้คุณมุ่งเน้นเฉพาะโค้ดของคุณได้เท่านั้น คุณจะแก้ไข ViewController.swift สําหรับส่วนที่เหลือของห้องทดลองนี้
- นําเข้าไลบรารี MLKitVision และ MLKit ImageLabeling โดยการเพิ่มโค้ดนี้ที่ด้านขวาบนในส่วนการนําเข้า UIKit ดังนี้
import MLKitVision
import MLKitImageLabeling
- จากนั้นเริ่มต้น ImageView โดยใช้ไฟล์ที่เราจัดกลุ่มไว้ในแอปภายในฟังก์ชัน
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
imageView.image = UIImage(named:"flower1.jpg")
}
- สร้างฟังก์ชันตัวช่วยสําหรับรับป้ายกํากับของรูปภาพ ซึ่งอยู่ใต้
viewDidLoad()
ดังนี้
func getLabels(with image: UIImage){
- สร้าง VisionImage จากรูปภาพ ML Kit ใช้ประเภทนี้เมื่อแยกประเภทรูปภาพ ดังนั้น ในฟังก์ชัน getlabel Func ให้เพิ่มโค้ดนี้:
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
- จากนั้นให้สร้างตัวเลือกสําหรับผู้ติดป้ายกํากับรูปภาพ โดยจะเริ่มต้นโดยใช้ตัวเลือกเหล่านี้ ในกรณีนี้ คุณเพิ่งตั้งค่าตัวเลือกพื้นฐานของ
confidenceThreshold
ซึ่งหมายความว่าคุณจะขอให้ผู้ติดป้ายกํากับแสดงป้ายกํากับที่มีความมั่นใจตั้งแต่ 0.4 ขึ้นไปเท่านั้น เช่น คําว่าดอกไม้ คลาสอย่าง "wood" หรือ "petal" จะมั่นใจมาก
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
- ต่อไปให้สร้างป้ายกํากับโดยใช้ตัวเลือกต่อไปนี้
let labeler = ImageLabeler.imageLabeler(options: options)
- เมื่อติดป้ายกํากับแล้ว คุณจะประมวลผลได้ ซึ่งจะแสดงโค้ดเรียกกลับที่มีป้ายกํากับพร้อมกัน (หากประสบความสําเร็จ) และข้อผิดพลาด (หากล้มเหลว) ซึ่งคุณจะประมวลผลในฟังก์ชันอื่นได้ซึ่งเราจะสร้างในอีกสักครู่
labeler.process(visionImage) { labels, error in
self.processResult(from: labels, error: error)
}
ไม่ต้องห่วงหาก Xcode บ่นว่าไม่มีสมาชิก processResult
คุณยังไม่ได้ดําเนินการดังกล่าว และคุณจะต้องดําเนินการต่อไป
เพื่อความสะดวก ให้เพลิดเพลินกับฟังก์ชัน getLabels แบบเต็ม:
// This is called when the user presses the button
func getLabels(with image: UIImage){
// Get the image from the UI Image element and set its orientation
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
// Create Image Labeler options, and set the threshold to 0.4
// so we will ignore all classes with a probability of 0.4 or less
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
// Initialize the labeler with these options
let labeler = ImageLabeler.imageLabeler(options: options)
// And then process the image, with the callback going to self.processresult
labeler.process(visionImage) { labels, error in
self.processResult(from: labels, error: error)
}
}
คราวนี้คุณจะต้องใช้ฟังก์ชัน processResult
วิธีการนี้ก็ง่ายมาก เพราะเรามีป้ายกํากับและออบเจ็กต์ข้อผิดพลาดที่ส่งกลับมาให้เรา คุณควรแคสต์ป้ายกํากับเป็นประเภท ImageLabel จาก ML Kit
เมื่อเสร็จแล้ว ให้ทําซ้ําชุดป้ายกํากับ ดึงคําอธิบาย และค่าความเชื่อมั่น แล้วเพิ่มไปยัง var
ที่ชื่อ labeltexts
เมื่อทําซ้ําทั้งหมดแล้ว คุณก็ตั้งค่า lbloutput.text เป็นค่านั้น
ฟังก์ชันที่สมบูรณ์มีดังนี้
// This gets called by the labeler's callback
func processResult(from labels: [ImageLabel]?, error: Error?){
// String to hold the labels
var labeltexts = ""
// Check that we have valid labels first
guard let labels = labels else{
return
}
// ...and if we do we can iterate through the set to get the description and confidence
for label in labels{
let labelText = label.text + " : " + label.confidence.description + "\n"
labeltexts += labelText
}
// And when we're done we can update the UI with the list of labels
lblOutput.text = labeltexts
}
ส่วนที่เหลือคือการเรียกใช้ getLabels
เมื่อผู้ใช้กดปุ่ม
เมื่อสร้างการดําเนินการทุกอย่างจะเรียบร้อยแล้ว เพียงอัปเดต IBAction
ที่ชื่อว่า doClassificaiton
ที่สร้างไว้ก่อนหน้านี้เพื่อโทรหา getLabels
โค้ดสําหรับเรียกใช้เนื้อหาด้วย imageView มีดังนี้
@IBAction func doClassification(_ sender: Any) {
getLabels(with: imageView.image!)
}
ตอนนี้ก็ลองใช้แอปได้เลย ดูการทํางานจริงได้ที่นี่
โปรดทราบว่าเลย์เอาต์อาจดูแตกต่างออกไปตามอุปกรณ์
Codelab จะไม่สํารวจเลย์เอาต์ประเภทต่างๆ ต่ออุปกรณ์ ซึ่งเป็นแนวคิดที่ซับซ้อน หากไม่เห็น UI อย่างถูกต้อง ให้กลับไปที่เครื่องมือแก้ไขสตอรีบอร์ด และคุณจะเห็นส่วนดูเป็น: ที่สามารถเลือกอุปกรณ์ได้ที่ด้านล่าง เลือกตัวเลือก 1 รายการให้ตรงกับรูปภาพหรืออุปกรณ์ที่คุณกําลังทดสอบ และแก้ไข UI ให้เหมาะกับอุปกรณ์นั้น
เมื่อใช้ประโยชน์จากการพัฒนา iOS มากขึ้น คุณจะได้เรียนรู้วิธีใช้ข้อจํากัดเพื่อให้ UI ของคุณสอดคล้องกันในโทรศัพท์ทุกเครื่อง แต่นอกขอบเขตของห้องทดลองนี้
12. ยินดีด้วย
ขณะนี้คุณใช้งานแอปทั้งบน Android และ iOS แล้ว ซึ่งจะช่วยให้คุณมองเห็นคอมพิวเตอร์พื้นฐานด้วยรูปแบบทั่วไป คุณทําการลดภาระงานส่วนใหญ่ไปแล้ว
ใน Codelab ถัดไป คุณจะสร้างโมเดลที่กําหนดเองที่ระบุดอกไม้ประเภทต่างๆ ได้ และเขียนโค้ดเพียงไม่กี่บรรทัด คุณก็จะนําโมเดลที่กําหนดเองในแอปนี้ไปใช้ให้เกิดประโยชน์มากขึ้นได้