Apple platformlarında Firebase Auth ve Functions'ı kullanarak Cloud Vision ile Görüntülerdeki Metni Güvenli Bir Şekilde Tanıyın

Uygulamanızdan bir Google Cloud API'sini çağırmak için yetkilendirmeyi yöneten ve API anahtarları gibi gizli değerleri koruyan bir ara REST API oluşturmanız gerekir. Daha sonra bu ara hizmette kimlik doğrulaması yapmak ve iletişim kurmak için mobil uygulamanıza kod yazmanız gerekir.

Bu REST API'yi oluşturmanın bir yolu, size kimlik doğrulamayı yöneten ve önceden oluşturulmuş SDK'larla mobil uygulamanızdan çağrılabilen Google Cloud API'lerine yönelik yönetilen, sunucusuz bir ağ geçidi sağlayan Firebase Authentication and Functions'ı kullanmaktır.

Bu kılavuz, uygulamanızdan Cloud Vision API'yi çağırmak için bu tekniğin nasıl kullanılacağını gösterir. Bu yöntem, kimliği doğrulanmış tüm kullanıcıların Cloud projeniz aracılığıyla Cloud Vision faturalı hizmetlerine erişmesine olanak tanır; bu nedenle, devam etmeden önce bu kimlik doğrulama mekanizmasının kullanım durumunuz için yeterli olup olmadığını değerlendirin.

Sen başlamadan önce

Projenizi yapılandırın

Firebase'i uygulamanıza henüz eklemediyseniz başlangıç ​​kılavuzundaki adımları izleyerek bunu yapın.

Firebase bağımlılıklarını yüklemek ve yönetmek için Swift Paket Yöneticisini kullanın.

  1. Xcode'da uygulama projeniz açıkken Dosya > Paket Ekle'ye gidin.
  2. İstendiğinde Firebase Apple platformları SDK deposunu ekleyin:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Firebase ML kitaplığını seçin.
  5. -ObjC bayrağını hedefinizin derleme ayarlarının Diğer Bağlayıcı Bayrakları bölümüne ekleyin.
  6. Bitirdiğinizde Xcode, bağımlılıklarınızı arka planda otomatik olarak çözmeye ve indirmeye başlayacaktır.

Ardından, bazı uygulama içi kurulumları gerçekleştirin:

  1. Uygulamanızda Firebase'i içe aktarın:

    Süratli

    import FirebaseMLModelDownloader

    Amaç-C

    @import FirebaseMLModelDownloader;

Birkaç yapılandırma adımı daha ve artık hazırız:

  1. Projeniz için Bulut tabanlı API'leri henüz etkinleştirmediyseniz şimdi yapın:

    1. Firebase konsolunun Firebase ML API'leri sayfasını açın.
    2. Projenizi henüz Blaze fiyatlandırma planına yükseltmediyseniz bunu yapmak için Yükselt'e tıklayın. (Yalnızca projeniz Blaze planında değilse yükseltme yapmanız istenecektir.)

      Yalnızca Blaze düzeyindeki projeler Bulut tabanlı API'leri kullanabilir.

    3. Bulut tabanlı API'ler henüz etkin değilse Bulut Tabanlı API'leri Etkinleştir'i tıklayın.
  2. Cloud Vision API'ye erişime izin vermemek için mevcut Firebase API anahtarlarınızı yapılandırın:
    1. Bulut konsolunun Kimlik Bilgileri sayfasını açın.
    2. Listedeki her API anahtarı için düzenleme görünümünü açın ve Anahtar Kısıtlamalar bölümünde Cloud Vision API dışındaki mevcut tüm API'leri listeye ekleyin.

Çağrılabilir işlevi dağıtma

Ardından, uygulamanız ile Cloud Vision API arasında köprü oluşturmak için kullanacağınız Bulut İşlevini dağıtın. functions-samples deposu kullanabileceğiniz bir örnek içerir.

Varsayılan olarak Cloud Vision API'ye bu işlev aracılığıyla erişim, yalnızca uygulamanızın kimliği doğrulanmış kullanıcılarının Cloud Vision API'ye erişmesine izin verecektir. Farklı gereksinimler için işlevi değiştirebilirsiniz.

İşlevi dağıtmak için:

  1. Function-samples deposunu kopyalayın veya indirin ve Node-1st-gen/vision-annotate-image dizinine geçin:
    git clone https://github.com/firebase/functions-samples
    cd Node-1st-gen/vision-annotate-image
    
  2. Bağımlılıkları yükleyin:
    cd functions
    npm install
    cd ..
    
  3. Firebase CLI'niz yoksa yükleyin .
  4. vision-annotate-image dizininde bir Firebase projesi başlatın. İstendiğinde listeden projenizi seçin.
    firebase init
  5. İşlevi dağıtın:
    firebase deploy --only functions:annotateImage

Firebase Auth'ı uygulamanıza ekleyin

Yukarıda dağıtılan çağrılabilir işlev, uygulamanızın kimliği doğrulanmamış kullanıcılarından gelen tüm istekleri reddeder. Henüz yapmadıysanız uygulamanıza Firebase Auth'u eklemeniz gerekecektir.

Uygulamanıza gerekli bağımlılıkları ekleyin

Firebase için Bulut İşlevleri kitaplığını yüklemek için Swift Paket Yöneticisini kullanın.

Artık resimlerdeki metni tanımaya hazırsınız.

1. Giriş görüntüsünü hazırlayın

Cloud Vision'ı çağırmak için görüntünün base64 kodlu bir dize olarak biçimlendirilmesi gerekir. Bir UIImage işlemek için:

Süratli

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

Amaç-C

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

2. Metni tanımak için çağrılabilir işlevi çağırın

Bir görüntüdeki yer işaretlerini tanımak için bir JSON Cloud Vision isteği ileten çağrılabilir işlevi çağırın.

  1. Öncelikle Cloud Functions'ın bir örneğini başlatın:

    Süratli

    lazy var functions = Functions.functions()
    

    Amaç-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Talebi oluşturun. Cloud Vision API iki tür metin algılamayı destekler: TEXT_DETECTION ve DOCUMENT_TEXT_DETECTION . İki kullanım durumu arasındaki fark için Cloud Vision OCR Dokümanlarına bakın.

    Süratli

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

    Amaç-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. Son olarak işlevi çağırın:

    Süratli

    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]
        }
        // ...
      }
    }
    

    Amaç-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. Tanınan metin bloklarından metni çıkarın

Metin tanıma işlemi başarılı olursa görev sonucunda BatchAnnotateImagesResponse'un JSON yanıtı döndürülür. Metin açıklamaları fullTextAnnotation nesnesinde bulunabilir.

Tanınan metni text alanında bir dize olarak alabilirsiniz. Örneğin:

Süratli

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)")
}

Amaç-C

NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);

Ayrıca görüntünün bölgelerine özel bilgiler de alabilirsiniz. Her block , paragraph , word ve symbol için bölgede tanınan metni ve bölgenin sınırlayıcı koordinatlarını alabilirsiniz. Örneğin:

Süratli

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
  }
}

Amaç-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];
  }
}