Apple প্ল্যাটফর্মে Firebase Auth ও Functions ব্যবহার করে Cloud Vision-এর মাধ্যমে নিরাপদে ছবির টেক্সট শনাক্ত করা

আপনার অ্যাপ থেকে Google Cloud API কল করার জন্য, আপনাকে একটি মধ্যবর্তী REST API তৈরি করতে হবে যা অনুমোদন ম্যানেজ করে এবং API কী-এর মতো গোপন মান সুরক্ষিত করে। তারপরে, এই মধ্যবর্তী পরিষেবার সাথে যাচাইকরণ ও যোগাযোগ করার জন্য আপনাকে মোবাইল অ্যাপে কোড লিখতে হবে।

Firebase যাচাইকরণ ও ফাংশন ব্যবহার করে এই REST API তৈরি করা যায়। এটি আপনাকে Google Cloud API-তে ম্যানেজ করা, সার্ভারলেস গেটওয়ে দেয় যা যাচাইকরণ ম্যানেজ করে এবং আগে থেকে তৈরি SDK-এর সাহায্যে আপনার মোবাইল অ্যাপ থেকে কল করা যায়।

এই গাইড থেকে আপনি জানতে পারবেন যে কীভাবে এই টেকনিক ব্যবহার করে আপনার অ্যাপ থেকে Cloud Vision API কল করতে হয়। এই পদ্ধতি আপনার Cloud প্রোজেক্টের মাধ্যমে সবকটি যাচাই করা ব্যবহারকারীকে Cloud Vision-এর বিল করা পরিষেবা অ্যাক্সেস করতে দেবে, তাই এগিয়ে যাওয়ার আগে এই যাচাইকরণ পদ্ধতি আপনার ব্যবহারের ক্ষেত্রে যথেষ্ট কিনা তা বিবেচনা করে দেখুন।

শুরু করার আগে

আপনার প্রোজেক্ট কনফিগার করা

আপনি যদি এখনও আপনার অ্যাপে Firebase যোগ না করে থাকেন, তাহলে শুরু করার নির্দেশিকাতে দেওয়া ধাপগুলি অনুসরণ করে এটি করুন।

Firebase ডিপেন্ডেন্সি ইনস্টল ও ম্যানেজ করতে Swift Package Manager ব্যবহার করুন।

  1. Xcode-এ, আপনার অ্যাপ প্রোজেক্ট খোলা থাকা অবস্থায়, ফাইল > প্যাকেজ যোগ করুন বিকল্পে নেভিগেট করুন।
  2. প্রম্পট করা হলে, Firebase Apple প্ল্যাটফর্ম SDK রিপোজিটরি যোগ করুন:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Firebase ML লাইব্রেরি বেছে নিন।
  5. আপনার টার্গেটের বিল্ড সেটিংসের অন্যান্য লিঙ্কার ফ্ল্যাগ বিভাগে -ObjC ফ্ল্যাগ যোগ করুন।
  6. এটি সম্পূর্ণ হয়ে গেলে, Xcode অটোমেটিক আপনার ডিপেন্ডেন্সি ব্যাকগ্রাউন্ডে সমাধান ও ডাউনলোড করা শুরু করবে।

এরপরে, অ্যাপ-মধ্যস্থ কিছু সেট-আপ করুন:

  1. আপনার অ্যাপে, Firebase ইমপোর্ট করুন:

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

আরও কয়েকটি কনফিগারেশন ধাপ এবং আমরা রেডি:

  1. আপনি যদি এখনও নিজের প্রোজেক্টের জন্য ক্লাউড-ভিত্তিক API চালু না করে থাকেন, তাহলে এখন করে নিন:

    1. Firebase কনসোলে Firebase ML API পৃষ্ঠা খুলুন।
    2. আপনি যদি আগে থেকেই নিজের প্রোজেক্টকে পে-অ্যাজ-ইউ-গো Blaze প্রাইসিং প্ল্যানে আপগ্রেড না করে থাকেন, তাহলে তা করতে আপগ্রেড করুন বিকল্পে ক্লিক করুন। (আপনার প্রোজেক্ট Blaze প্রাইসিং প্ল্যানে না থাকলে তবেই আপনাকে আপগ্রেড করার জন্য প্রম্পট করা হবে।)

      শুধুমাত্র Blaze প্রাইসিং প্ল্যানের প্রোজেক্টই ক্লাউড-ভিত্তিক API ব্যবহার করতে পারে।

    3. ক্লাউড-ভিত্তিক API আগে থেকেই চালু করা না থাকলে, ক্লাউড-ভিত্তিক API চালু করুন বিকল্পে ক্লিক করুন।
  2. Cloud Vision API-তে অ্যাক্সেস বন্ধ করতে আপনার আগে থেকে থাকা Firebase API কী কনফিগার করুন:
    1. Cloud Console-এর শংসাপত্র পৃষ্ঠা খুলুন।
    2. তালিকায় থাকা প্রতিটি API কী-এর জন্য, এডিটিং ভিউ খুলুন এবং 'কী বিধিনিষেধ' বিভাগে, Cloud Vision API বাদ দিয়ে উপলভ্য সব API তালিকায় যোগ করুন।

কল করা যায় এমন ফাংশন ডেপ্লয় করা

এরপরে, আপনার অ্যাপ ও Cloud Vision API-এর মধ্যে ব্রিজ তৈরি করতে যে ক্লাউড ফাংশন ব্যবহার করবেন সেটি ডিপ্লয় করুন। functions-samples রিপোজিটরিতে একটি উদাহরণ আছে যা আপনি ব্যবহার করতে পারেন।

ডিফল্ট হিসেবে, এই ফাংশনের মাধ্যমে Cloud Vision API অ্যাক্সেস করলে, আপনার অ্যাপের শুধুমাত্র যাচাই করা ব্যবহারকারীরাই Cloud Vision API অ্যাক্সেস করতে পারবেন। বিভিন্ন প্রয়োজনীয়তা অনুযায়ী আপনি ফাংশন পরিবর্তন করতে পারবেন।

ফাংশন ডেপ্লয় করতে:

  1. functions-samples repo ক্লোন বা ডাউনলোড করুন এবং Node-1st-gen/vision-annotate-image ডিরেক্টরিতে পরিবর্তন করুন:
    git clone https://github.com/firebase/functions-samples
    cd Node-1st-gen/vision-annotate-image
    
  2. ডিপেন্ডেন্সি ইনস্টল করুন:
    cd functions
    npm install
    cd ..
  3. আপনার Firebase CLI না থাকলে, এটি ইনস্টল করুন।
  4. vision-annotate-image ডিরেক্টরিতে Firebase প্রোজেক্ট শুরু করুন। প্রম্পট করা হলে, তালিকা থেকে আপনার প্রোজেক্ট বেছে নিন।
    firebase init
  5. ফাংশন ডেপ্লয় করুন:
    firebase deploy --only functions:annotateImage

আপনার অ্যাপে Firebase Auth যোগ করা

উপরে ডিপ্লয় করা কল করা যায় এমন ফাংশন আপনার অ্যাপের যাচাই না করা ব্যবহারকারীদের থেকে আসা যেকোনও অনুরোধ বাতিল করে দেবে। আপনি যদি এটি আগে না করে থাকেন, তাহলে আপনাকে আপনার অ্যাপে Firebase Auth যোগ করতে হবে।

আপনার অ্যাপে প্রয়োজনীয় ডিপেন্ডেন্সি যোগ করুন

Cloud Functions for Firebase লাইব্রেরি ইনস্টল করতে Swift Package Manager ব্যবহার করুন।

এখন আপনি ছবির টেক্সট শনাক্ত করা শুরু করতে পারবেন।

১. ইনপুট ছবি প্রস্তুত করা

Cloud Vision-কে কল করার জন্য, ছবিটিকে অবশ্যই base64-encoded স্ট্রিং হিসেবে ফর্ম্যাট করতে হবে। 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];

২. টেক্সট শনাক্ত করতে কল করা যায় এমন ফাংশন ইনভোক করা

কোনও ছবিতে ল্যান্ডমার্ক শনাক্ত করতে, JSON Cloud Vision অনুরোধ পাস করে কল করা যায় এমন ফাংশন ইনভোক করুন।

  1. প্রথমে, Cloud Functions-এর একটি ইনস্ট্যান্স ইনিশিয়ালাইজ করুন:

    Swift

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. অনুরোধ তৈরি করুন। Cloud Vision API-তে টেক্সট শনাক্তকরণের দুটি ধরন কাজ করে: TEXT_DETECTION ও DOCUMENT_TEXT_DETECTION। দুটি ব্যবহারের ক্ষেত্রে পার্থক্য জানতে Cloud Vision OCR ডকুমেন্ট দেখুন।

    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"]}
    };
    
  3. সবশেষে, ফাংশনটি ইনভোক করুন:

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

৩. শনাক্ত করা টেক্সটের ব্লক থেকে টেক্সট এক্সট্র্যাক্ট করা

টেক্সট শনাক্তকরণ অপারেশন সফল হলে, টাস্কের ফলাফলে BatchAnnotateImagesResponse -এর JSON উত্তর রিটার্ন করা হবে। টেক্সট অ্যানোটেশন 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];
  }
}