مسح المستندات والتعرف على النص باستخدام VisionKit و Vision Framework على iOS

سنقوم اليوم بمسح المستند ضوئيًا وعرض النص الذي تم التعرف عليه من هذا المستند. لا تحتاج إلى تثبيت مكتبات إضافية لهذا الغرض : VisionKit مفيد للمسح الضوئي و Vision للتعرف على النص.



أولاً ، تأكد من تثبيت Xcode 11 و iOS 13 ، ثم قم بإنشاء مشروع جديد بدعم Storyboard .

سنقوم بالمسح الضوئي باستخدام كاميرا فيديو. لذلك نحن بحاجة إلى إضافة NSCameraUsageDescription إلى Info.plist ، بدون هذا التطبيق سوف يتعطل.



يتم المسح


لمسح المستندات ضوئيًا ، نستخدم VisionKit Framework . لفتح الشاشة للمسح الضوئي ، تحتاج إلى إنشاء عينة جديدة من VNDocumentCameraViewController والإخراج:

let scanner = VNDocumentCameraViewController()
scanner.delegate = self
present(scanner, animated: true)

إضافة VNDocumentCameraViewControllerDelegate إلى ViewController :

class ViewController: UIViewController, VNDocumentCameraViewControllerDelegate {
...

بعد النقر على "إلغاء" أو خطأ ، أغلق الشاشة المفتوحة:

func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
  controller.dismiss(animated: true)
}

func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
  controller.dismiss(animated: true)
}

بعد المسح والنقر على "حفظ" ، سيعمل ما يلي:

func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
  for i in 0 ..< scan.pageCount {
    let img = scan.imageOfPage(at: i)
    // recognizeText(inImage: img)
  }
  controller.dismiss(animated: true)
}

يمكن معالجة كل صفحة على حدة.

التعرف على النص


اكتشفنا الفحص ، والآن نستخرج النص.

لجعل كل شيء يسير بسلاسة ، سنقوم بالاعتراف في الخلفية. للقيام بذلك ، قم بإنشاء DispatchQueue :

lazy var workQueue = {
  return DispatchQueue(label: "workQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
}()

للاعتراف ، نحتاج إلى VNImageRequestHandler مع صورة و VNRecognizeTextRequest مع خيارات التعرف على المستوى ، و CustomWords ، و التعرف على اللغات ، بالإضافة إلى معالج إكمال يعطي النتيجة في شكل نص. عند الانتهاء ، نجمع أفضل خيارات النص ونعرض:

lazy var textRecognitionRequest: VNRecognizeTextRequest = {
    let req = VNRecognizeTextRequest { (request, error) in
        guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
        
        var resultText = ""
        for observation in observations {
            guard let topCandidate = observation.topCandidates(1).first else { return }
            resultText += topCandidate.string
            resultText += "\n"
        }
        
        DispatchQueue.main.async {
            self.txt.text = resultText
        }
    }
    return req
}()

VNImageRequestHandler :

func recognizeText(inImage: UIImage) {
    guard let cgImage = inImage.cgImage else { return }
    
    workQueue.async {
        let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        do {
            try requestHandler.perform([self.textRecognitionRequest])
        } catch {
            print(error)
        }
    }
}

أحدث ViewController


import UIKit
import Vision
import VisionKit

class ViewController: UIViewController, VNDocumentCameraViewControllerDelegate {
    @IBOutlet weak var txt: UITextView!
    
    lazy var workQueue = {
        return DispatchQueue(label: "workQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
    }()
    
    lazy var textRecognitionRequest: VNRecognizeTextRequest = {
        let req = VNRecognizeTextRequest { (request, error) in
            guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
            
            var resultText = ""
            for observation in observations {
                guard let topCandidate = observation.topCandidates(1).first else { return }
                resultText += topCandidate.string
                resultText += "\n"
            }
            
            DispatchQueue.main.async {
                self.txt.text = self.txt.text + "\n" + resultText
            }
        }
        return req
    }()

    @IBAction func startScan(_ sender: Any) {
        txt.text = ""
        
        let scanner = VNDocumentCameraViewController()
        scanner.delegate = self
        present(scanner, animated: true)
    }
    
    func recognizeText(inImage: UIImage) {
        guard let cgImage = inImage.cgImage else { return }
        
        workQueue.async {
            let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
            do {
                try requestHandler.perform([self.textRecognitionRequest])
            } catch {
                print(error)
            }
        }
    }
    
    // MARK: - Document Camera VC Delegate
    
    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
        for i in 0 ..< scan.pageCount {
            let img = scan.imageOfPage(at: i)
            recognizeText(inImage: img)
        }
        
        controller.dismiss(animated: true)
    }
    
    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
        controller.dismiss(animated: true)
    }
    
    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
        print(error)
        controller.dismiss(animated: true)
    }
    
}




ماذا بعد؟


التوثيق:
developer.apple.com/documentation/vision
developer.apple.com/documentation/visionkit

فيديو إطار عمل WWDC:
developer.apple.com/videos/all-videos/؟q=

مشروع Vision GitHub:
github.com/usenbekov / رؤية تجريبية

Source: https://habr.com/ru/post/undefined/


All Articles