Сканирование документов и распознавание текстов на них (с помощью VisionKit и Vision Framework)

от автора

Сегодня мы будем сканировать документ и выводить на экран распознанный текст в этом документе. Для этого нам не нужно устанавливать дополнительные библиотеки. Мы используем VisionKit Framework для сканирования документа и Vision Framework для распознавания текстов.

Для начало убедитесь что у вас стоит Xcode 11 и iOS 13, потом создайте новый проект.

Сканирование совершим с помощью видео камеры. Значит нам нужно добавить 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 с опциями как recognitionLevel, customWords, recognitionLanguages, а также обработчик завершения, который даст результат в текстовом виде. При завершении, собираем самые лучшие варианты текстов и показываем на экране:

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 видео про Speech framework:
developer.apple.com/videos/all-videos/?q=Vision

Ссылка на github проект находится здесь:
github.com/usenbekov/vision-demo

ссылка на оригинал статьи https://habr.com/ru/post/487868/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *