หากต้องการเรียก Google Cloud API จากแอป คุณต้องสร้าง REST API ระดับกลางที่จัดการการให้สิทธิ์และปกป้องค่าลับ เช่น คีย์ API จากนั้นคุณต้อง เขียนโค้ดในแอปบนอุปกรณ์เคลื่อนที่เพื่อตรวจสอบสิทธิ์และสื่อสารกับบริการระดับกลางนี้
วิธีหนึ่งในการสร้าง REST API นี้คือการใช้ Firebase Authentication และ Functions ซึ่งจะมอบเกตเวย์แบบไม่มีเซิร์ฟเวอร์ที่จัดการให้คุณเพื่อเข้าถึง Google Cloud API ที่จัดการการตรวจสอบสิทธิ์และสามารถเรียกใช้จากแอปบนอุปกรณ์เคลื่อนที่ด้วย SDK ที่สร้างไว้ล่วงหน้า
คู่มือนี้แสดงวิธีใช้เทคนิคนี้เพื่อเรียก Cloud Vision API จากแอป วิธีนี้จะช่วยให้ผู้ใช้ที่ผ่านการตรวจสอบสิทธิ์ทั้งหมดเข้าถึงบริการ Cloud Vision ที่มีการเรียกเก็บเงินผ่านโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของคุณได้ ดังนั้น โปรดพิจารณาว่ากลไกการตรวจสอบสิทธิ์นี้เพียงพอสำหรับ Use Case ของคุณหรือไม่ก่อนดำเนินการต่อ
ก่อนเริ่มต้น
กำหนดค่าโปรเจ็กต์
หากยังไม่ได้เพิ่ม Firebase ลงในแอป ให้ทำตาม ขั้นตอนในคู่มือเริ่มต้นใช้งานใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase
- เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ File > Add Packages
- เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ Firebase Apple Platforms SDK ดังนี้
- เลือกไลบรารี Firebase ML
- เพิ่มแฟล็ก
-ObjCลงในส่วน Other Linker Flags ของการตั้งค่าบิลด์ของเป้าหมาย - เมื่อเสร็จแล้ว Xcode จะเริ่มจับคู่ข้อมูลและดาวน์โหลด ทรัพยากร Dependency ในเบื้องหลังโดยอัตโนมัติ
https://github.com/firebase/firebase-ios-sdk.git
จากนั้นทำการตั้งค่าบางอย่างในแอป ดังนี้
- นำเข้า Firebase ในแอปโดยใช้คำสั่ง
Swift
import FirebaseMLModelDownloader
Objective-C
@import FirebaseMLModelDownloader;
ทำตามขั้นตอนการกำหนดค่าอีก 2-3 ขั้นตอน แล้วคุณก็พร้อมใช้งาน
-
หากยังไม่ได้เปิดใช้ Cloud-based APIs สำหรับโปรเจ็กต์ ให้ทำดังนี้
- เปิดหน้า Firebase ML APIs ในคอนโซล Firebase
-
หากยังไม่ได้อัปเกรดโปรเจ็กต์เป็น แพ็กเกจราคา Blaze แบบจ่ายเมื่อใช้ ให้คลิก อัปเกรด เพื่อดำเนินการ (ระบบจะ แจ้งให้คุณอัปเกรดก็ต่อเมื่อโปรเจ็กต์ไม่ได้ใช้ แพ็กเกจราคา Blaze)
เฉพาะโปรเจ็กต์ที่ใช้แพ็กเกจราคา Blaze เท่านั้นที่ใช้ Cloud-based APIs ได้
- หากยังไม่ได้เปิดใช้ Cloud-based APIs ให้คลิก เปิดใช้ Cloud-based APIs
- กำหนดค่าคีย์ Firebase API ที่มีอยู่เพื่อไม่อนุญาตการเข้าถึง Cloud
Vision API:
- เปิดหน้า ข้อมูลเข้าสู่ระบบ ของ Cloud Console
- สำหรับคีย์ API แต่ละรายการในรายการ ให้เปิดมุมมองการแก้ไข แล้วในส่วนข้อจำกัดคีย์ ให้เพิ่ม API ที่มีทั้งหมด ยกเว้น Cloud Vision API ลงในรายการ
ทำให้ฟังก์ชันที่เรียกใช้ได้ใช้งานได้
จากนั้นทำให้ Cloud Function ที่คุณจะใช้เพื่อเชื่อมต่อแอปกับ Cloud
Vision API ใช้งานได้ ที่เก็บ functions-samples มีตัวอย่าง
ที่คุณใช้ได้
โดยค่าเริ่มต้น การเข้าถึง Cloud Vision API ผ่านฟังก์ชันนี้จะอนุญาตให้ เฉพาะผู้ใช้แอปที่ผ่านการตรวจสอบสิทธิ์เข้าถึง Cloud Vision API ได้ คุณสามารถ แก้ไขฟังก์ชันให้ตรงกับข้อกำหนดต่างๆ ได้
วิธีทำให้ฟังก์ชันใช้งานได้
- โคลนหรือดาวน์โหลดที่เก็บ functions-samples
แล้วเปลี่ยนเป็นไดเรกทอรี
Node-1st-gen/vision-annotate-imageโดยใช้คำสั่งต่อไปนี้git clone https://github.com/firebase/functions-samplescd Node-1st-gen/vision-annotate-image - ติดตั้งทรัพยากร Dependency โดยใช้คำสั่งต่อไปนี้
cd functionsnpm installcd .. - หากยังไม่มี Firebase CLI ให้ติดตั้ง
- เริ่มต้นโปรเจ็กต์ Firebase ในไดเรกทอรี
vision-annotate-imageเมื่อได้รับข้อความแจ้ง ให้เลือกโปรเจ็กต์ในรายการfirebase init
- ทำให้ฟังก์ชันใช้งานได้โดยใช้คำสั่งต่อไปนี้
firebase deploy --only functions:annotateImage
เพิ่ม Firebase Auth ลงในแอป
ฟังก์ชันที่เรียกใช้ได้ซึ่งทำให้ใช้งานได้ข้างต้นจะปฏิเสธคำขอจากผู้ใช้แอปที่ไม่ได้ผ่านการตรวจสอบสิทธิ์ คุณจะต้องเพิ่ม Firebase Auth ลงในแอปหากยังไม่ได้ดำเนินการ
เพิ่มทรัพยากร Dependency ที่จำเป็นลงในแอป
ใช้ Swift Package Manager เพื่อติดตั้งไลบรารี Cloud Functions for Firebase
ตอนนี้คุณพร้อมที่จะเริ่มจดจำข้อความในรูปภาพแล้ว
1. เตรียมรูปภาพอินพุต
หากต้องการเรียก Cloud Vision รูปภาพต้องจัดรูปแบบเป็นสตริงที่มีการเข้ารหัสฐาน 64 วิธีประมวลผลUIImage
Swift
guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return } let base64encodedImage = imageData.base64EncodedString()
Objective-C
NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f); NSString *base64encodedImage = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
2. เรียกใช้ฟังก์ชันที่เรียกใช้ได้เพื่อจดจำข้อความ
หากต้องการจดจำสถานที่สำคัญในรูปภาพ ให้เรียกใช้ฟังก์ชันที่เรียกใช้ได้โดยส่งคำขอ Cloud Vision ในรูปแบบ JSONขั้นแรก ให้เริ่มต้นอินสแตนซ์ของ Cloud Functions โดยใช้คำสั่งต่อไปนี้
Swift
lazy var functions = Functions.functions()Objective-C
@property(strong, nonatomic) FIRFunctions *functions;สร้างคำขอโดยใช้คำสั่งต่อไปนี้ Cloud Vision API รองรับการตรวจหาข้อความ 2 ประเภท ได้แก่
TEXT_DETECTIONและDOCUMENT_TEXT_DETECTIONดูความแตกต่างระหว่างกรณีการใช้งานทั้ง 2 ประเภทได้ที่เอกสาร OCR ของ Cloud VisionSwift
let requestData = [ "image": ["content": base64encodedImage], "features": ["type": "TEXT_DETECTION"], "imageContext": ["languageHints": ["en"]] ]Objective-C
NSDictionary *requestData = @{ @"image": @{@"content": base64encodedImage}, @"features": @{@"type": @"TEXT_DETECTION"}, @"imageContext": @{@"languageHints": @[@"en"]} };สุดท้าย ให้เรียกใช้ฟังก์ชันโดยใช้คำสั่งต่อไปนี้
Swift
do { let result = try await functions.httpsCallable("annotateImage").call(requestData) print(result) } catch { if let error = error as NSError? { if error.domain == FunctionsErrorDomain { let code = FunctionsErrorCode(rawValue: error.code) let message = error.localizedDescription let details = error.userInfo[FunctionsErrorDetailsKey] } // ... } }Objective-C
[[_functions HTTPSCallableWithName:@"annotateImage"] callWithObject:requestData completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) { if (error) { if ([error.domain isEqualToString:@"com.firebase.functions"]) { FIRFunctionsErrorCode code = error.code; NSString *message = error.localizedDescription; NSObject *details = error.userInfo[@"details"]; } // ... } // Function completed succesfully // Get information about labeled objects }];
3. แยกข้อความออกจากบล็อกข้อความที่จดจำ
หากการดำเนินการจดจำข้อความสำเร็จ ระบบจะแสดงผลการตอบกลับ JSON ของ
BatchAnnotateImagesResponse
ในผลลัพธ์ของงาน คุณดูคำอธิบายประกอบข้อความได้ในออบเจ็กต์
fullTextAnnotation
คุณสามารถรับข้อความที่จดจำได้เป็นสตริงในช่อง text เช่น
Swift
let annotation = result.flatMap { $0.data as? [String: Any] }
.flatMap { $0["fullTextAnnotation"] }
.flatMap { $0 as? [String: Any] }
guard let annotation = annotation else { return }
if let text = annotation["text"] as? String {
print("Complete annotation: \(text)")
}
Objective-C
NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);
นอกจากนี้ คุณยังรับข้อมูลที่เฉพาะเจาะจงกับภูมิภาคของรูปภาพได้ด้วย สำหรับ block, paragraph, word และ symbol แต่ละรายการ คุณจะได้รับข้อความที่จดจำในภูมิภาคและพิกัดขอบเขตของภูมิภาค เช่น
Swift
guard let pages = annotation["pages"] as? [[String: Any]] else { return }
for page in pages {
var pageText = ""
guard let blocks = page["blocks"] as? [[String: Any]] else { continue }
for block in blocks {
var blockText = ""
guard let paragraphs = block["paragraphs"] as? [[String: Any]] else { continue }
for paragraph in paragraphs {
var paragraphText = ""
guard let words = paragraph["words"] as? [[String: Any]] else { continue }
for word in words {
var wordText = ""
guard let symbols = word["symbols"] as? [[String: Any]] else { continue }
for symbol in symbols {
let text = symbol["text"] as? String ?? ""
let confidence = symbol["confidence"] as? Float ?? 0.0
wordText += text
print("Symbol text: \(text) (confidence: \(confidence)%n")
}
let confidence = word["confidence"] as? Float ?? 0.0
print("Word text: \(wordText) (confidence: \(confidence)%n%n")
let boundingBox = word["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
print("Word bounding box: \(boundingBox.description)%n")
paragraphText += wordText
}
print("%nParagraph: %n\(paragraphText)%n")
let boundingBox = paragraph["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
print("Paragraph bounding box: \(boundingBox)%n")
let confidence = paragraph["confidence"] as? Float ?? 0.0
print("Paragraph Confidence: \(confidence)%n")
blockText += paragraphText
}
pageText += blockText
}
}
Objective-C
for (NSDictionary *page in annotation[@"pages"]) {
NSMutableString *pageText = [NSMutableString new];
for (NSDictionary *block in page[@"blocks"]) {
NSMutableString *blockText = [NSMutableString new];
for (NSDictionary *paragraph in block[@"paragraphs"]) {
NSMutableString *paragraphText = [NSMutableString new];
for (NSDictionary *word in paragraph[@"words"]) {
NSMutableString *wordText = [NSMutableString new];
for (NSDictionary *symbol in word[@"symbols"]) {
NSString *text = symbol[@"text"];
[wordText appendString:text];
NSLog(@"Symbol text: %@ (confidence: %@\n", text, symbol[@"confidence"]);
}
NSLog(@"Word text: %@ (confidence: %@\n\n", wordText, word[@"confidence"]);
NSLog(@"Word bounding box: %@\n", word[@"boundingBox"]);
[paragraphText appendString:wordText];
}
NSLog(@"\nParagraph: \n%@\n", paragraphText);
NSLog(@"Paragraph bounding box: %@\n", paragraph[@"boundingBox"]);
NSLog(@"Paragraph Confidence: %@\n", paragraph[@"confidence"]);
[blockText appendString:paragraphText];
}
[pageText appendString:blockText];
}
}