หากต้องการเรียกใช้ Google Cloud API จากแอป คุณต้องสร้าง REST API ระดับกลางที่จัดการการให้สิทธิ์และปกป้องค่าลับ เช่น คีย์ API จากนั้นคุณต้องเขียนโค้ดในแอปบนอุปกรณ์เคลื่อนที่เพื่อตรวจสอบสิทธิ์และสื่อสารกับบริการสื่อกลางนี้
วิธีหนึ่งในการสร้าง REST API นี้คือการใช้ Firebase Authentication และ Functions ซึ่งจะให้เกตเวย์แบบไม่มีเซิร์ฟเวอร์ที่มีการจัดการสำหรับ Google Cloud API ที่จัดการการตรวจสอบสิทธิ์และเรียกใช้ได้จากแอปบนอุปกรณ์เคลื่อนที่ด้วย SDK ที่สร้างขึ้นล่วงหน้า
คู่มือนี้จะแสดงวิธีใช้เทคนิคนี้เพื่อเรียกใช้ Cloud Vision API จากแอปของคุณ วิธีนี้จะอนุญาตให้ผู้ใช้ที่ผ่านการตรวจสอบสิทธิ์ทุกคนเข้าถึงบริการแบบชําระเงินของ Cloud Vision ผ่านโปรเจ็กต์ Cloud ของคุณ ดังนั้นโปรดพิจารณาว่ากลไกการตรวจสอบสิทธิ์นี้เพียงพอกับกรณีการใช้งานของคุณหรือไม่ก่อนดําเนินการต่อ
ก่อนเริ่มต้น
กำหนดค่าโปรเจ็กต์
หากยังไม่ได้เพิ่ม Firebase ลงในแอป ให้ทําตามขั้นตอนในคู่มือการเริ่มต้นใช้งานใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase
- เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ไฟล์ > เพิ่มแพ็กเกจ
- เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ Firebase SDK สำหรับแพลตฟอร์ม Apple ดังนี้
- เลือกคลัง Firebase ML
- เพิ่ม Flag
-ObjC
ลงในส่วน Other Linker Flags ของการตั้งค่าบิลด์เป้าหมาย - เมื่อเสร็จแล้ว Xcode จะเริ่มจับคู่ข้อมูลและดาวน์โหลดทรัพยากร Dependency ในเบื้องหลังโดยอัตโนมัติ
https://github.com/firebase/firebase-ios-sdk.git
ถัดไป ให้ตั้งค่าบางอย่างในแอป ดังนี้
- นําเข้า Firebase ในแอป โดยทําดังนี้
import FirebaseMLModelDownloader
@import FirebaseMLModelDownloader;
ขั้นตอนการกำหนดค่าอีก 2-3 ขั้นตอน แล้วเราก็จะพร้อมใช้งาน
-
หากยังไม่ได้เปิดใช้ API ที่อยู่ในระบบคลาวด์สําหรับโปรเจ็กต์ ให้ทําดังนี้
- เปิดFirebase ML หน้า API ของคอนโซล Firebase
-
หากยังไม่ได้อัปเกรดโปรเจ็กต์เป็นแพ็กเกจราคา Blaze ให้คลิกอัปเกรด (ระบบจะแจ้งให้คุณอัปเกรดเฉพาะในกรณีที่โปรเจ็กต์ไม่ได้อยู่ในแพ็กเกจ Blaze)
เฉพาะโปรเจ็กต์ระดับ Blaze เท่านั้นที่ใช้ API บนระบบคลาวด์ได้
- หากยังไม่ได้เปิดใช้ API ที่อยู่ในระบบคลาวด์ ให้คลิกเปิดใช้ API ที่อยู่ในระบบคลาวด์
- กำหนดค่าคีย์ 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 repo และเปลี่ยนเป็นไดเรกทอรี
Node-1st-gen/vision-annotate-image
git clone https://github.com/firebase/functions-samples
cd Node-1st-gen/vision-annotate-image
- ติดตั้งการอ้างอิง
cd functions
npm install
cd ..
- หากไม่มี Firebase CLI ให้ติดตั้ง
- เริ่มต้นโปรเจ็กต์ Firebase ในไดเรกทอรี
vision-annotate-image
เมื่อได้รับข้อความแจ้ง ให้เลือกโปรเจ็กต์ในรายการfirebase init
- ทำให้ฟังก์ชันใช้งานได้โดยทำดังนี้
firebase deploy --only functions:annotateImage
เพิ่ม Firebase Auth ไปยังแอป
ฟังก์ชันที่เรียกใช้ได้ซึ่งติดตั้งใช้งานด้านบนจะปฏิเสธคําขอจากผู้ใช้แอปที่ไม่ได้ตรวจสอบสิทธิ์ คุณจะต้องเพิ่ม Firebase Auth ลงในแอป หากยังไม่ได้ดำเนินการ
เพิ่มการพึ่งพาที่จำเป็นลงในแอป
ใช้ Swift Package Manager เพื่อติดตั้งไลบรารี Cloud Functions for Firebase
ตอนนี้คุณก็พร้อมที่จะเริ่มจดจำข้อความในรูปภาพแล้ว
1. เตรียมรูปภาพอินพุต
รูปภาพต้องอยู่ในรูปแบบสตริงที่เข้ารหัส Base64 จึงจะเรียกใช้ Cloud Vision ได้ วิธีประมวลผลUIImage
guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return } let base64encodedImage = imageData.base64EncodedString()
NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f); NSString *base64encodedImage = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
2. เรียกใช้ฟังก์ชันที่เรียกใช้ได้เพื่อจดจําข้อความ
หากต้องการจดจำจุดสังเกตในรูปภาพ ให้เรียกใช้ฟังก์ชันที่เรียกใช้ได้โดยส่งคำขอ JSON Cloud Visionก่อนอื่น ให้เริ่มต้นอินสแตนซ์ของ Cloud Functions โดยทำดังนี้
lazy var functions = Functions.functions()
@property(strong, nonatomic) FIRFunctions *functions;
สร้างคำขอ Cloud Vision API รองรับประเภทการตรวจจับข้อความ 2 ประเภท ได้แก่
TEXT_DETECTION
และDOCUMENT_TEXT_DETECTION
ดูความแตกต่างระหว่างกรณีการใช้งาน 2 รูปแบบได้ในเอกสาร OCR ของ Cloud Visionlet requestData = [ "image": ["content": base64encodedImage], "features": ["type": "TEXT_DETECTION"], "imageContext": ["languageHints": ["en"]] ]
NSDictionary *requestData = @{ @"image": @{@"content": base64encodedImage}, @"features": @{@"type": @"TEXT_DETECTION"}, @"imageContext": @{@"languageHints": @[@"en"]} };
สุดท้าย ให้เรียกใช้ฟังก์ชัน
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] } // ... } }
[[_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
เช่น
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)")
}
NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);
นอกจากนี้ คุณยังดูข้อมูลที่เจาะจงสำหรับภูมิภาคของรูปภาพได้ด้วย สําหรับ block
,
paragraph
, word
และ symbol
แต่ละรายการ คุณสามารถดูข้อความที่ระบบจดจําได้ในภูมิภาคนั้นๆ และพิกัดขอบเขตของภูมิภาค เช่น
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
}
}
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];
}
}