Digitalização de documentos e reconhecimento de texto com o VisionKit e o Vision Framework no iOS

Hoje, digitalizaremos o documento e exibiremos o texto reconhecido neste documento. Você não precisa instalar bibliotecas adicionais para isso: o VisionKit é útil para digitalização e o Vision para reconhecimento de texto.



Primeiro, verifique se você possui o Xcode 11 e o iOS 13 instalados e crie um novo projeto com o suporte do Storyboard .

Vamos digitalizar usando uma câmera de vídeo. Portanto, precisamos adicionar NSCameraUsageDescription ao Info.plist , sem esse aplicativo ele trava.



Digitalização


Para digitalizar documentos, usamos o VisionKit Framework . Para abrir a tela para digitalização, é necessário criar uma nova amostra do VNDocumentCameraViewController e saída:

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

Adicione VNDocumentCameraViewControllerDelegate ao ViewController :

class ViewController: UIViewController, VNDocumentCameraViewControllerDelegate {
...

Após clicar em "Cancelar" ou um erro, feche a tela aberta:

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

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

Após digitalizar e clicar em "Salvar", o seguinte funcionará:

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

Cada página pode ser processada individualmente.

Reconhecimento de texto


Nós descobrimos a digitalização, agora extraímos o texto.

Para que tudo corra bem, realizaremos o reconhecimento em segundo plano. Para fazer isso, crie um DispatchQueue :

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

Para reconhecimento, precisamos de um VNImageRequestHandler com uma imagem e VNRecognizeTextRequest com as opções reconhecimentoLevel , customWords , reconhecimentoLanguages , bem como um manipulador de conclusão que fornecerá o resultado em forma de texto. Após a conclusão, coletamos as melhores opções de texto e exibimos:

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

Último 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)
    }
    
}




Qual é o próximo?


Documentação:
developer.apple.com/documentation/vision
developer.apple.com/documentation/visionkit

Vídeo da estrutura do WWDC Speech:
developer.apple.com/videos/all-videos/?q=Vision

Projeto GitHub:
github.com/usenbekov / vision-demo

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


All Articles