Để gọi một Google Cloud API qua ứng dụng, bạn cần tạo một API REST trung gian giúp xử lý việc uỷ quyền và bảo vệ các giá trị bí mật, chẳng hạn như khoá API. Sau đó, bạn cần viết mã trong ứng dụng di động của mình để xác thực và giao tiếp với dịch vụ trung gian này.
Một cách để tạo API REST này là sử dụng chức năng và tính năng Xác thực Firebase. Phương thức này cung cấp cho bạn một cổng vào không có máy chủ để truy cập vào Google Cloud API, giúp xử lý việc xác thực và có thể được gọi qua ứng dụng di động bằng SDK tạo sẵn.
Hướng dẫn này minh hoạ cách dùng kỹ thuật này để gọi API Cloud Vision từ ứng dụng của bạn. Phương thức này sẽ cho phép tất cả người dùng đã xác thực truy cập vào các dịch vụ có tính phí của Cloud Vision thông qua dự án Cloud của bạn. Vì vậy, hãy cân nhắc xem cơ chế xác thực này có đủ cho trường hợp sử dụng của bạn hay không trước khi tiếp tục.
Trước khi bắt đầu
Định cấu hình dự án
Nếu bạn chưa thêm Firebase vào ứng dụng của mình, hãy thêm Firebase bằng cách làm theo các bước trong hướng dẫn bắt đầu sử dụng.Sử dụng Trình quản lý gói Swift để cài đặt và quản lý các phần phụ thuộc Firebase.
- Trong Xcode, khi dự án ứng dụng của bạn đang mở, hãy chuyển đến File > Add Packages (Tệp > Thêm gói).
- Khi được nhắc, hãy thêm kho lưu trữ SDK nền tảng Apple của Firebase:
- Chọn thư viện máy học Firebase.
- Thêm cờ
-ObjC
vào mục Cờ trình liên kết khác trong chế độ cài đặt bản dựng của mục tiêu. - Khi hoàn tất, Xcode sẽ tự động bắt đầu phân giải và tải các phần phụ thuộc của bạn xuống ở chế độ nền.
https://github.com/firebase/firebase-ios-sdk.git
Tiếp theo, hãy thực hiện một số thiết lập trong ứng dụng:
- Trong ứng dụng của bạn, hãy nhập Firebase:
Swift
import FirebaseMLModelDownloader
Objective-C
@import FirebaseMLModelDownloader;
Một vài bước định cấu hình nữa và chúng ta đã sẵn sàng bắt đầu:
-
Nếu bạn chưa bật API trên đám mây cho dự án của mình, hãy bật ngay:
- Mở trang API ML của Firebase trong bảng điều khiển của Firebase.
-
Nếu bạn chưa nâng cấp dự án của mình lên Gói linh hoạt, hãy nhấp vào Nâng cấp để thực hiện việc này. (Bạn sẽ chỉ được nhắc nâng cấp nếu dự án của bạn không phải là Gói linh hoạt.)
Chỉ các dự án cấp Blaze mới có thể sử dụng API trên đám mây.
- Nếu bạn chưa bật API trên đám mây, hãy nhấp vào Bật API dựa trên đám mây.
- Định cấu hình các khoá API Firebase hiện có để không cho phép truy cập vào Cloud Vision API:
- Mở trang Thông tin đăng nhập của bảng điều khiển Cloud.
- Đối với mỗi khoá API trong danh sách, hãy mở khung hiển thị chỉnh sửa. Trong phần Hạn chế khoá, hãy thêm tất cả API có sẵn ngoại trừ Cloud Vision API vào danh sách.
Triển khai hàm có thể gọi
Tiếp theo, hãy triển khai Cloud Function bạn sẽ sử dụng để làm cầu nối cho ứng dụng của mình và Cloud Vision API. Kho lưu trữ functions-samples
chứa một ví dụ mà bạn có thể sử dụng.
Theo mặc định, việc truy cập Cloud Vision API thông qua chức năng này sẽ chỉ cho phép những người dùng đã xác thực trong ứng dụng của bạn truy cập vào Cloud Vision API. Bạn có thể sửa đổi hàm này theo các yêu cầu khác nhau.
Cách triển khai hàm:
- Sao chép hoặc tải kho lưu trữ hàm-mẫu xuống rồi thay đổi sang thư mục
Node-1st-gen/vision-annotate-image
:git clone https://github.com/firebase/functions-samples
cd Node-1st-gen/vision-annotate-image
- Cài đặt phần phụ thuộc:
cd functions
npm install
cd ..
- Nếu bạn chưa có Giao diện dòng lệnh (CLI) của Firebase, hãy cài đặt giao diện này.
- Khởi chạy một dự án Firebase trong thư mục
vision-annotate-image
. Khi được nhắc, hãy chọn dự án của bạn trong danh sách.firebase init
- Triển khai hàm:
firebase deploy --only functions:annotateImage
Thêm tính năng Xác thực Firebase vào ứng dụng
Hàm có thể gọi được triển khai ở trên sẽ từ chối mọi yêu cầu của người dùng ứng dụng chưa được xác thực. Nếu chưa xác thực, bạn sẽ phải thêm tính năng Xác thực Firebase vào ứng dụng.
Thêm các phần phụ thuộc cần thiết vào ứng dụng
Sử dụng Trình quản lý gói Swift để cài đặt thư viện Cloud Functions cho Firebase.
Bây giờ, bạn đã sẵn sàng bắt đầu nhận dạng văn bản trong hình ảnh.
1. Chuẩn bị hình ảnh đầu vào
Để gọi Cloud Vision, hình ảnh phải được định dạng dưới dạng một chuỗi được mã hoá base64. Cách xử lý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. Gọi hàm có thể gọi để nhận dạng văn bản
Để nhận dạng các mốc trong một hình ảnh, hãy gọi hàm có thể gọi truyền một yêu cầu Tầm nhìn đám mây JSON.Trước tiên, hãy khởi chạy một bản sao của Cloud Functions:
Swift
lazy var functions = Functions.functions()
Objective-C
@property(strong, nonatomic) FIRFunctions *functions;
Tạo yêu cầu. Cloud Vision API hỗ trợ 2 Loại phát hiện văn bản:
TEXT_DETECTION
vàDOCUMENT_TEXT_DETECTION
. Xem Tài liệu nhận dạng ký tự quang học (OCR) của Cloud Vision để biết sự khác biệt giữa 2 trường hợp sử dụng.Swift
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"]} };
Cuối cùng, hãy gọi hàm này:
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. Trích xuất văn bản từ các khối văn bản được nhận dạng
Nếu thao tác nhận dạng văn bản thành công, phản hồi JSON của BatchDialogImagesResponse sẽ được trả về trong kết quả của tác vụ. Bạn có thể tìm thấy các chú giải văn bản trong đối tượng fullTextAnnotation
.
Bạn có thể lấy văn bản được nhận dạng dưới dạng chuỗi trong trường text
. Ví dụ:
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"]);
Bạn cũng có thể xem thông tin cụ thể theo các khu vực trên hình ảnh. Đối với mỗi block
, paragraph
, word
và symbol
, bạn có thể nhận dạng văn bản trong khu vực và toạ độ giới hạn của khu vực. Ví dụ:
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];
}
}