Catch up on everything we announced at this year's Firebase Summit. Learn more

จดจำข้อความในรูปภาพได้อย่างปลอดภัยด้วย Cloud Vision โดยใช้ Firebase Auth และฟังก์ชั่นบนแพลตฟอร์ม Apple

ในการเรียก Google Cloud API จากแอปของคุณ คุณต้องสร้าง REST API ระดับกลางที่จัดการการให้สิทธิ์และปกป้องค่าลับ เช่น คีย์ API จากนั้นคุณจะต้องเขียนโค้ดในแอพมือถือของคุณเพื่อตรวจสอบและสื่อสารกับบริการระดับกลางนี้

วิธีหนึ่งในการสร้าง REST API นี้คือการใช้ Firebase Authentication and Functions ซึ่งให้เกตเวย์แบบไร้เซิร์ฟเวอร์ที่มีการจัดการไปยัง Google Cloud API ที่จัดการการตรวจสอบสิทธิ์ และสามารถเรียกได้จากแอปบนอุปกรณ์เคลื่อนที่ด้วย SDK ที่สร้างไว้ล่วงหน้า

คู่มือนี้สาธิตวิธีใช้เทคนิคนี้เพื่อเรียก Cloud Vision API จากแอปของคุณ วิธีนี้จะอนุญาตให้ผู้ใช้ที่ตรวจสอบสิทธิ์ทั้งหมดเข้าถึงบริการที่เรียกเก็บเงิน Cloud Vision ผ่านโปรเจ็กต์ Cloud ของคุณ ดังนั้นให้พิจารณาว่ากลไกการตรวจสอบสิทธิ์นี้เพียงพอสำหรับกรณีการใช้งานของคุณหรือไม่ก่อนดำเนินการต่อ

ก่อนจะเริ่ม

กำหนดค่าโครงการของคุณ

หากคุณยังไม่ได้เพิ่ม Firebase แอปของคุณทำเช่นนั้นโดยทำตามขั้นตอนในส่วน คู่มือการเริ่มต้น

ใช้ Swift Package Manager เพื่อติดตั้งและจัดการการพึ่งพา Firebase

  1. ใน Xcode กับโครงการของคุณเปิดแอปนำทางไปยังไฟล์> สวิฟท์แพคเกจ> เพิ่มแพคเกจการพึ่งพา
  2. เมื่อได้รับแจ้ง ให้เพิ่มที่เก็บ SDK ของแพลตฟอร์ม Firebase Apple:
  3.   https://github.com/firebase/firebase-ios-sdk
      
  4. เลือกไลบรารี Firebase ML
  5. เมื่อเสร็จแล้ว Xcode จะเริ่มแก้ไขและดาวน์โหลดการพึ่งพาของคุณในเบื้องหลังโดยอัตโนมัติ

ถัดไป ทำการตั้งค่าบางอย่างในแอพ:

  1. ในแอปของคุณ ให้นำเข้า Firebase:

    Swift

    import Firebase

    วัตถุประสงค์-C

    @import Firebase;

อีกสองสามขั้นตอนการกำหนดค่า และเราพร้อมที่จะไป:

  1. หากคุณยังไม่ได้เปิดใช้งาน API แบบ Cloud-based สำหรับโปรเจ็กต์ของคุณ ให้ดำเนินการดังนี้:

    1. เปิด หน้า Firebase ML APIs ของคอนโซล Firebase
    2. หากคุณไม่ได้อัปเกรดแล้วโครงการของคุณแผนกำหนดราคา Blaze คลิกอัพเกรดจะทำเช่นนั้น (คุณจะได้รับแจ้งให้อัปเกรดเฉพาะเมื่อโปรเจ็กต์ของคุณไม่อยู่ในแผน Blaze)

      เฉพาะโปรเจ็กต์ระดับ Blaze เท่านั้นที่สามารถใช้ API แบบคลาวด์ได้

    3. หาก APIs cloud-based ยังไม่ได้เปิดใช้งานแล้วคลิกเปิดใช้งาน API ของ cloud-based
  2. กำหนดค่าคีย์ Firebase API ที่มีอยู่ของคุณเพื่อไม่อนุญาตให้เข้าถึง Cloud Vision API:
    1. เปิด ข้อมูลประจำตัว หน้าของคอนโซลเมฆ
    2. สำหรับแต่ละคีย์ API ในรายการเปิดมุมมองการแก้ไขและในส่วนข้อ จำกัด ที่สำคัญเพิ่มทั้งหมดของ API ที่มีอยู่ยกเว้น API เมฆวิสัยทัศน์ในรายการ

ปรับใช้ฟังก์ชันที่เรียกได้

ขั้นต่อไป ปรับใช้ Cloud Function ที่คุณจะใช้เพื่อเชื่อมโยงแอปของคุณและ Cloud Vision API functions-samples ที่เก็บมีตัวอย่างเช่นคุณสามารถใช้

ตามค่าเริ่มต้น การเข้าถึง Cloud Vision API ผ่านฟังก์ชันนี้จะอนุญาตให้เฉพาะผู้ใช้ที่ตรวจสอบสิทธิ์ของแอปของคุณเข้าถึง Cloud Vision API ได้ คุณสามารถปรับเปลี่ยนฟังก์ชันสำหรับข้อกำหนดต่างๆ ได้

ในการปรับใช้ฟังก์ชัน:

  1. โคลนหรือ Download ฟังก์ชั่นตัวอย่าง repo และการเปลี่ยนแปลงไปสู่ vision-annotate-image ไดเรกทอรี:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. ติดตั้งการอ้างอิง:
    cd functions
    npm install
    cd ..
    
  3. หากคุณไม่ได้มี Firebase CLI, ติดตั้ง
  4. เริ่มต้นโครงการ Firebase ใน vision-annotate-image ไดเรกทอรี เมื่อได้รับแจ้ง ให้เลือกโครงการของคุณในรายการ
    firebase init
  5. การจัดวางฟังก์ชั่น:
    firebase deploy --only functions:annotateImage

เพิ่ม Firebase Auth ในแอปของคุณ

ฟังก์ชัน callable ที่ปรับใช้ด้านบนจะปฏิเสธคำขอใดๆ จากผู้ใช้ที่ไม่ผ่านการตรวจสอบสิทธิ์ของแอปของคุณ หากคุณยังไม่ได้ทำเช่นนั้นคุณจะต้อง เพิ่ม Firebase Auth แอปของคุณ

เพิ่มการพึ่งพาที่จำเป็นให้กับแอปของคุณ

ใช้ Swift Package Manager เพื่อติดตั้ง Cloud Functions for Firebase library

ตอนนี้คุณพร้อมที่จะเริ่มจดจำข้อความในรูปภาพแล้ว

1. เตรียมอิมเมจอินพุต

ในการเรียก Cloud Vision รูปภาพต้องได้รับการจัดรูปแบบเป็นสตริงที่เข้ารหัส base64 ในการประมวลผล UIImage :

Swift

guard let imageData = uiImage.jpegData(compressionQuality: 1.0f) else { return }
let base64encodedImage = imageData.base64EncodedString()

วัตถุประสงค์-C

NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
NSString *base64encodedImage =
  [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];

2. เรียกใช้ฟังก์ชันที่เรียกได้เพื่อจดจำข้อความ

สถานที่สำคัญที่จะรับรู้ในภาพเรียกใช้ฟังก์ชั่น callable ผ่าน คำขอ JSON เมฆวิสัยทัศน์

  1. ขั้นแรก เริ่มต้นอินสแตนซ์ของ Cloud Functions:

    Swift

    lazy var functions = Functions.functions()
    

    วัตถุประสงค์-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. สร้างคำขอ เมฆวิสัยทัศน์ API สนับสนุนทั้งสอง ประเภท ของการตรวจสอบข้อความ: TEXT_DETECTION และ DOCUMENT_TEXT_DETECTION ดู เมฆวิสัยทัศน์ OCR เอกสาร สำหรับความแตกต่างระหว่างทั้งสองกรณีการใช้งาน

    Swift

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["type": "TEXT_DETECTION"],
      "imageContext": ["languageHints": ["en"]]
    ]
    

    วัตถุประสงค์-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. ในที่สุด เรียกใช้ฟังก์ชัน:

    Swift

    functions.httpsCallable("annotateImage").call(requestData) { (result, error) in
      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]
        }
        // ...
      }
      // Function completed succesfully
    }
    

    วัตถุประสงค์-C

    [[_functions HTTPSCallableWithName:@"annotateImage"]
                              callWithObject:requestData
                                  completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
            if (error) {
              if (error.domain == FIRFunctionsErrorDomain) {
                FIRFunctionsErrorCode code = error.code;
                NSString *message = error.localizedDescription;
                NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
              }
              // ...
            }
            // Function completed succesfully
            // Get information about labeled objects
    
          }];
    

3. แยกข้อความจากบล็อกของข้อความที่รู้จัก

หากการดำเนินการรับรู้ข้อความที่ประสบความสำเร็จในการตอบสนองของ JSON BatchAnnotateImagesResponse จะกลับมาในผลงานของ คำอธิบายประกอบข้อความที่สามารถพบได้ใน fullTextAnnotation วัตถุ

คุณจะได้รับข้อความที่ได้รับการยอมรับเป็นสตริงในส่วน text ฟิลด์ ตัวอย่างเช่น:

Swift

guard let annotation = (result?.data as? [String: Any])?["fullTextAnnotation"] as? [String: Any] else { return }
print("%nComplete annotation:")
let text = annotation["text"] as? String ?? ""
print("%n\(text)")

วัตถุประสงค์-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
}

วัตถุประสงค์-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];
  }
}