รู้จัก ML Kit for Firebase ตั้งแต่ Zero จนเป็น Hero

Jirawatee
Firebase Thailand

--

ยุคนี้มีคนให้ความสนใจเรื่อง Deep Learning อย่างกว้างขวาง โดยข้อมูลจาก Google Trends บอกว่าความสนใจมีเพิ่มขึ้นกว่า 50 เท่าเมื่อเทียบกับ 8 ปีที่แล้ว นั่นก็เพราะเครื่องมือและเทคโนโลยีสมัยนี้มีประสิทธิภาพสูง ช่วยให้การวิเคราะห์มีความแม่นยำสูงขึ้น นำไปใช้งานได้ง่ายมากยิ่งขึ้น รวมถึงสร้างมูลค่าให้กับธุรกิจอย่างมหาศาล

ML Kit for Firebase เป็น Mobile SDK ที่จะนำพลังของ Google Machine Learning มาสู่แอปของคุณทั้ง Android และ iOS ไม่ว่าคุณจะเป็นมืออาชีพหรือมือใหม่ด้าน Machine Learning ก็สามารถเริ่มต้นได้ง่ายๆ เพียงเขียนโค้ดไม่กี่บรรทัด

ML Kit for Firebase มาพร้อมกับ 5 features พื้นฐานที่นักพัฒนา mobile app ได้ใช้กันเป็นประจำ (จะขออธิบายสรรพคุณแต่ละ feature ในขั้นตอนการพัฒนา)

ซึ่งทั้ง 5 features นี้สามารถจะใช้งานได้ทั้งแบบ On-device และ in the Cloud

  • On-device: รวดเร็ว ทำงานได้แม้ไม่มีอินเตอร์เน็ต และไม่มีค่าใช้จ่าย
  • in the Cloud: แม่นยำกว่าด้วยพลังของ Machine Learning ใน GCP พร้อมโควต้าฟรี 1,000 requests / feature / เดือน

ส่วนในกรณีที่มีเคสที่เฉพาะเจาะจงนอกเหนือจาก 5 features ด้านบน เช่น ต้องการทราบประเภทของดอกไม้ในรูป หรือสายพันธุ์ปลาในรูป เราก็สามารถใช้โมเดล TensorFlow Lite ที่เป็นไฟล์ .tflite จากภายนอกได้ (จะมีบทความแยกหลังจากทีม Firebase ปล่อยตัว Compression นะครับ)

คราวนี้เรามาดูกันหน่อยว่า feature ไหนมีใน On-device หรือบน Cloud บ้าง

จากตารางจะสังเกตว่าจะมีแค่ Landmark recognition ตัวเดียวที่ต้องประมวลผลใน Cloud ส่วน Text recognition และ Image labeling จะมีทางเลือกให้ทั้ง On-device และบน Cloud ในกรณีที่ต้องการความแม่นยำสูง

เกริ่นมาซะยาวเลย ใครที่กำลังอ่านบทความนี้อยู่คงคันไม้คันมือกันเต็มที่แล้วสินะ ว่าที่บอกว่าง่ายเพียงโค้ดไม่กี่บรรทัดมันจริงไหม งั้นเรามาดูขั้นตอนในการพัฒนากันเลยว่ามีอะไรบ้าง

  1. การติดตั้ง Firebase และ SDK ของ ML Kit for Firebase ในโปรเจค
  2. การสร้าง FirebaseVisionImage เพื่อใช้กับ 5 use cases
  3. Text Recognition
  4. Face Detection
  5. Barcode Scanning
  6. Image Labeling
  7. Landmark Recognition

ตัวอย่างที่จะแสดงจะเป็นของ Android นะครับ จริงๆโค้ดของ Android กับ iOS มี concept ที่เหมือนกัน ดังนั้นอ่านตรงนี้เข้าใจ ก็ไปพัฒนาฝั่ง iOS ได้แล้วครับ

1. การติดตั้ง Firebase และ SDK ของ ML Kit ในโปรเจค

ถ้าผู้อ่านสร้างโปรเจคใหม่ ให้ไปดูการติดตั้ง Firebase ในบทความนี้ก่อน

กรณีประมวลผลบน Cloud: คุณจำเป็นต้องใช้ Blaze plan ซึ่งสามารถเปลี่ยนได้ใน Firebase Console เนื่องจากจะต้องมีการใช้ Cloud Vision API ซึ่งอยู่เป็นเบื้องหลังการทำงาน และจะต้อง enable บริการ Cloud Vision API ที่ลิงค์นี้ก่อน https://console.cloud.google.com/apis/library/vision.googleapis.com/ โดยอย่าลืมว่า enable ให้ตรงกับโปรเจคของเรา ซึ่งชื่อจะแสดงที่ส่วนบนของหน้า

เมื่อติดตั้ง Firebase เรียบร้อยแล้ว ก็ให้เพิ่ม SDK ของ ML Kit for Firebase ใน build.gradle ของ app-level แล้วกด sync ก็เป็นอันจบส่วนที่ 1 ละ

dependencies {
...
implementation 'com.google.firebase:firebase-ml-vision:19.0.3'

// กรณีใช้ image labeling
implementation 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2'
}

Optional: ถ้าคุณต้องการประมวลผลแบบ On-device ขอแนะนำให้เพิ่ม meta-data ด้านล่างนี้ลงใน AndroidManifest.xml เพราะหลังจากติดตั้งแอปแล้ว มันจะทำการ download โมเดลต่างๆที่ระบุใน value อัตโนมัติ ทำให้แอปพร้อมใช้งานทันที

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

<application ...>
...
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="ocr, face, barcode, label" />
</application>

2. การสร้าง FirebaseVisionImage เพื่อใช้กับทั้ง 5 features

เนื่องจากทั้ง 5 features จะต้องใช้ input ที่เป็นภาพในการประมวลผล ดังนั้นจุดเริ่มขบวนเราจึงต้องสร้าง FirebaseVisonImage กันก่อน โดยเราสามารถสร้างได้หลายวิธีดังนี้

  • สร้างจาก Bitmap: วิธีนี้รูปต้องตั้งตรง ไม่กลับหัว ไม่ตะแคงข้างถึงจะ work
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
  • สร้างจาก media.Image object: ก่อนอื่นเราต้องหาองศาที่เหมาะสมจาก device rotation และแนวของ sensor ในกล้อง เพื่อให้ FirebaseVisionImage ที่ถูกสร้างมีมุมที่ต้องและประมวลผลได้แม่นยำขึ้น โดยมีโค้ดในการหาองศาตามด้านล่างนี้

เมื่อได้ค่า media.Image และ rotation มาแล้ว ก็สร้าง FirebaseVisionImage โลด

FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
  • สร้างจาก ByteBuffer หรือ byte array: โดยเริ่มต้นให้ไปหาค่า rotation แบบด้านบนก่อน หลังจากนั้นให้สร้าง FirebaseVisionImageMetadata object จากความกว้าง, ความสูง, Encoding format ของสี และค่า rotation ขึ้นมา
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setWidth(1280)
.setHeight(720)
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setRotation(rotation)
.build();

เมื่อได้ค่า buffer หรือ byte array พร้อมทั้ง FirebaseVisionImageMetadata มาแล้วก็สร้าง FirebaeVisionImage ได้

// กรณีรูปที่ได้มาเป็น buffer
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
// กรณีรูปที่ได้มาเป็น byteArray
FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
  • สร้างจาก File: วิธีนี้ให้ส่งค่า context และ URI ของไฟล์เข้าไปสร้าง
FirebaseVisionImage image;
try {
image = FirebaseVisionImage.fromFilePath(context, uri);
} catch (IOException e) {
e.printStackTrace();
}

3. Text Recognition

Text Recognition คือการแกะข้อความออกมาจากรูปภาพ โดย feature นี้จะช่วยให้ผู้ใช้สะดวกสบายขึ้นเช่น การกรอกข้อมูลในบัตรประชาชน หรือ การกรอกเลขสลากกินแบ่งเพื่อตรวจสอบ เป็นต้น ซึ่ง feature นี้เราสามารถพัฒนาได้ทั้งแบบ On-device และ Cloud โดยจะต่างกันตรงที่ on-device จะแกะตัวอักษร Latin ได้เท่านั้นซึ่งก็คือภาษาอังกฤษและตัวเลข แต่บน Cloud จะสามารถแกะได้หลายภาษา รวมทั้งภาษาไทย และอักขระพิเศษได้ด้วย

3.1 On-device

เริ่มต้นให้ get ค่า instance จากตัว FirebaseVisionTextDetector

FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ detectInImage แล้วรอ callback

หาก success เราจะได้ FirebaseVisionText กลับมา ซึ่งภายในจะมี text อยู่

3.2 in the Cloud

ปกติ cloud detector จะมีค่ามาตรฐานของตัว model เป็นแบบ stable และจะคืนผลลัพธ์กลับมา 10 ข้อความ แต่หากเราต้องการลองเล่น model ตัวล่าสุด(ซึ่งยังไม่เสถียร) ก็สามารถทำได้โดยการสร้าง FirebaseVisionCloudTextRecognizerOptions ขึ้นมา แล้ว setModelType เป็น LATEST_MODEL

FirebaseVisionCloudTextRecognizerOptions options =
new FirebaseVisionCloudTextRecognizerOptions.Builder()
.setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
.build();

พร้อมแล้วก็เริ่มจาก get ค่า instance

FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getCloudTextRecognizer();// กรณีต้องการตั้งค่าเอง
// FirebaseVisionTextRecognizer detector =
// FirebaseVision.getInstance().getCloudTextRecognizer(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ detectInImage แล้วรอ callback

หาก success เราจะได้ FirebaseVisionText กลับมา ซึ่งเราสามารถแกะ text ออกมาได้

4. Face Dectection

Face Detection คือการระบุรูปหน้าคนซึ่งสามารถระบุได้หลายหน้าใน 1 ภาพ แบบ On-device โดยสามารถระบุพิกัดของ หู ตา แก้ม ปาก จมูก นอกจากนั้นยังสามารถตรวจจับได้ว่าหน้านั้นยิ้มหรือไม่ ลืมตาหรือหลับตา และสามารถประมวลทำงานได้แบบ realtime ดังนั้นเราก็สามารถนำ feature ไปใช้ในการระบุการแสดงออกทั้งในภาพ วิดีโอหรือเกมได้

ก่อนจะเริ่มวิธีการ dectect ใบหน้า หากต้องการจะเปลี่ยนการตั้งค่าพื้นฐานของ model ก็สามารถดู config ต่างๆในตารางด้านล่างนี้

ตัวอย่างการตั้งค่า config

FirebaseVisionFaceDetectorOptions options = new FirebaseVisionFaceDetectorOptions.Builder()
.setModeType(FirebaseVisionFaceDetectorOptions.ACCURATE_MODE)
.setLandmarkType(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
.setClassificationType(
FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS
)
.build();

เริ่มต้นจากการ get ค่า instance จาก FirebaseVisionFaceDetector

FirebaseVisionFaceDetector detector = FirebaseVision.getInstance().getVisionFaceDetector(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ detectInImage แล้วรอ callback

หาก success เราจะได้ List ของ FirebaseVisionFace objects กลับมา ซึ่งเราสามารถแกะข้อมูลต่างๆจากหน้าที่ detect ออกมาได้

5. Barcode Scanning

Barcode scanning คือ การอ่านข้อมูลที่ได้รับการ encode แบบ On-device ตามมาตรฐาน barcode format ต่างๆไม่ว่ารูปจะอยู่ในแนวไหนก็สามารถอ่านได้ ซึ่งรวมถึง QR code ด้วย และมาตรฐานที่รองรับมีดังต่อไปนี้

  • Linear formats: Codabar, Code 39, Code 93, Code 128, EAN-8, EAN-13, ITF, UPC-A, UPC-E
  • 2D formats: Aztec, Data Matrix, PDF417, QR Code

ซึ่งในกรณีที่เป็น 2D formats จะรองรับรูปแบบของข้อมูลมากมายเช่น URLs, contact information, calendar events, email, phone numbers, SMS message prompts, geographic location และอื่นๆ

ก่อนจะเริ่มตัว barcode scanning หากเรารู้มาตรฐานที่ barcode เราจะใช้แบบเฉพาะเจาะจง ขอแนะนำให้ตั้งค่าแบบระบุไปเลย ด้วยการสร้าง FirebaseVisionBarcodeDetectorOptions เพราะจะทำให้การประมวลผลเร็วขึ้นอีก

ตัวอย่างคือการระบุให้ scan เฉพาะ QR code เท่านั้น

FirebaseVisionBarcodeDetectorOptions options = new FirebaseVisionBarcodeDetectorOptions.Builder()
.setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
.build();

เริ่มได้ อันดับแรกก็ get ค่า instance จาก FirebaseVisionBarcodeDetector

FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance().getVisionBarcodeDetector();

// กรณีที่ระบุ format แบบเฉพาะเจาะจง
//
FirebaseVisionBarcodeDetector detector = //FirebaseVision.getInstance().getVisionBarcodeDetector(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ detectInImage แล้วรอ callback

หาก success เราจะได้ List ของ FirebaseVisionBarcode objects กลับมา ซึ่งเราสามารถแกะข้อมูลต่างๆออกมาได้

6. Image Labeling

Image Labeling คือ การหา content ต่างๆจากภาพ เช่น คน สัตว์ สิ่งของ สถานที่ กิจกรรม และอื่นๆอีกมากมาย ซึ่งมีทั้งแบบ On-device และ in the Cloud โดยความต่างจะอยู่ที่จำนวนของ Label โดยหากเป็น On-device จะมี label พื้นฐานอยู่ 400 แบบ แต่ถ้าเป็นแบบ in the Cloud จะมี label มากกว่า 10,000 เลย ดังนั้นความละเอียดในการ match กับ label แบบ cloud จึงเฉพาะเจาะจงกว่า ตัวอย่างเช่น

6.1 On-device

ก่อนจะเริ่มพัฒนา หากเราต้องการตั้งค่าความแม่นยำของผลลัพธ์ที่ต้องการ เช่นต้องการความแม่นยำที่ 0.8 ขึ้นไป(1 คือแม่นยำ 100%) เราสามารถสร้าง FirebaseVisionLabelDetectorOptions แล้วกำหนดค่าความแม่นยำที่ต้องการได้

FirebaseVisionOnDeviceImageLabelerOptions options = new FirebaseVisionOnDeviceImageLabelerOptions.Builder()
.setConfidenceThreshold(0.8f)
.build();

แล้วก็เริ่มด้วยการ get ค่า instance จาก FirebaseVisionLabelDetector

FirebaseVisionImageLabeler detector = FirebaseVision.getInstance().getOnDeviceImageLabeler();

// กรณีต้องการตั้งค่าความแม่นยำต่ำสุดที่รับได้
// FirebaseVisionImageLabeler detector =
// FirebaseVision.getInstance().getOnDeviceImageLabeler(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ processImage แล้วรอ callback

หาก success เราจะได้ List ของ FirebaseVisionImageLabel objects กลับมา ซึ่งเราสามารถแกะข้อมูลต่างๆออกมาได้

for (FirebaseVisionImageLabel label: labels) {
String text = label.getLabel();
String entityId = label.getEntityId();
float confidence = label.getConfidence();
}

6.2 in the Cloud

ปกติ cloud detector จะมีค่ามาตรฐานของตัว model เป็นแบบ stable และจะคืนผลลัพธ์กลับมา 10 ข้อความ แต่หากเราต้องตั้งค่าเองก็สามารถทำได้โดยการสร้าง FirebaseVisionCloudDetectorOptions ขึ้นมา

FirebaseVisionCloudImageLabelerOptions options =
new FirebaseVisionCloudImageLabelerOptions.Builder()
.setConfidenceThreshold(0.7f)
.build();

เริ่มจาก get ค่า instance

FirebaseVisionImageLabeler detector = FirebaseVision.getInstance().getCloudImageLabeler();// กรณีต้องการตั้งค่าเอง
// FirebaseVisionImageLabeler detector = //FirebaseVision.getInstance().getCloudImageLabeler(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ processImage แล้วรอ callback

หาก success เราจะได้ List ของ FirebaseVisionImageLabel objects กลับมา ซึ่งเราสามารถแกะข้อมูลต่างๆออกมาได้

for (FirebaseVisionImageLabel label: labels) {
String text = label.getLabel();
String entityId = label.getEntityId();
float confidence = label.getConfidence();
}

7. Landmark Recognition

Landmark Recognition คือ หาชื่อสถานที่ที่ค่อนข้างเป็นที่รู้จักจากในภาพ แบบ in the Cloud พร้อมบอกพิกัด location ให้ด้วย

ปกติ cloud detector จะมีค่ามาตรฐานของตัว model เป็นแบบ stable และจะคืนผลลัพธ์กลับมา 10 ข้อความ แต่หากเราต้องการลอง model ตัวล่าสุด(ที่ยังไม่เสถียร) หรือจำนวนผลลัพธ์ที่ต้องการ ก็สามารถตั้งค่าเองได้ โดยการสร้าง FirebaseVisionCloudDetectorOptions ขึ้นมา

ตัวอย่างต้องการโมเดลแบบล่าสุดและผลลัพธ์ 5 ตัวแรก

FirebaseVisionCloudDetectorOptions options = new FirebaseVisionCloudDetectorOptions.Builder()
.setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
.setMaxResults(5)
.build();

เริ่มต้นจากการ get ค่า instance ของ FirebaseVisionCloudLandmarkDetector

FirebaseVisionCloudLandmarkDetector detector = FirebaseVision.getInstance().getVisionCloudLandmarkDetector();

// กรณีต้องการตั้งค่าเอง
// FirebaseVisionCloudLandmarkDetector detector =
// FirebaseVision.getInstance()
// .getVisionCloudLandmarkDetector(options);

จากนั้นก็ส่ง FirebaseVisionImage จากข้อ 2 เข้า method ชื่อ detectInImage แล้วรอ callback

หาก success เราจะได้ List ของ FirebaseVisionCloudLandmark objects กลับมา ซึ่งเราสามารถแกะข้อมูลต่างๆออกมาได้

สรุป

ML Kit for Firebase ถือเป็น step ที่สองที่ทีม Firebase นำเทคโนโลยี Google Machine Learning เข้ามา หลังจากปลายปีที่แล้วทีม Firebase ได้เปิดตัว Firebase Prediction ไป

โดยในอนาคต ML Kit for Firebase จะโฟกัสไปที่ 4 เรื่องหลักคือ Vision, Speech, Text และการ Custom Model ซึ่งเร็วๆนี้ก็จะมี feature ใหม่ออกมาอีก 2 ตัวคือ Face Contour(วิเคราะห์รูปร่างใบหน้า) และ Smart Reply(แนะนำประโยคตอบกลับ) ใครอยากลองเล่นก่อนก็สามารถสมัครเข้าร่วมทดสอบได้ที่ g.co/firebase/SignUp และสำหรับ source code ทั้งหมดสามารถ download มาศึกษาได้ที่

สุดท้ายนี้ก็หวังว่าบทความนี้จะช่วยให้ทุกท่านสามารถนำเทคโนโลยี Machine Learning ไปสร้างและมอบประสบการณ์ที่ดีกว่าให้ผู้ใช้ของคุณ กับขั้นตอนในการพัฒนาที่ง่ายด้วย ML Kit for Firebase แล้วพบกันใหม่บทความหน้า ราตรีสวัสดิ์นักพัฒนาชาวไทย

--

--

Jirawatee
Firebase Thailand

Technology Evangelist at LINE Thailand / Google Developer Expert in Firebase