Владислав Вчерашний, iOS-разработчик, рассказал об использовании VisionKit.
Возвращаясь в уже, казалось бы, далёкий 2017-й год на ежегодную конференцию Apple для разработчиков WWDC, мало кто вспомнит, что тогда нам впервые показали фреймворк под названием Vision. На тот момент он умел не так уж и много:
- Распознавать лица и штрих-коды;
- Определять текст;
- идентифицировать плоскости.
Так же фреймворк позволял классифицировать или распознавать объекты, использую Core ML модели.
Решив испытать новые возможности iOS? я быстро побежал создавать новый проект, читать документацию и тестировать новые фичи iOS. Каким же было моё удивление, когда я увидел рамку вокруг текста – но вот текст, к сожалению, так и не был распознан. Как так получилось? В Apple решили, что мне достаточно указать место, где есть текст, а вот распознавать я должен самостоятельно. На этом ТОГДА мое желание тестировать Vision закончилось :)
Вскоре, спустя два года, на WWDC 2019 мы получили долгожданное обновление фреймворка, который теперь умеет распознавать текст. Важно отметить, что распознавание текста с помощью VisionKit доступно только в iOS 13, а вот для более ранних версий рекомендую использовать WeScan.
Вступление
VisionKit – это небольшой фреймворк, который позволяет распознавать текст в вашем приложении, используя системный сканер документов (как в Notes.app).
Давайте на примере кратко ознакомимся с возможностями VisionKit, а также с его помощью научимся распознавать текст с документов.
Приступая к работе с VisionKit
Создайте проект на основе Single View App.
Откройте ViewController и импортируйте Vision и VisionKit:
Далее откройте Main.storyboard и добавьте в него 3 элемента
- UIButton –– для вызова VNDocumentCameraViewController;
- UIImageView –– для отображения сделанной фотографии;
- UITextView –– для отображения распознанного текста.
Сканирование документов
В VisionKit Apple добавила новый ViewController – VNDocumentCameraViewController. Как говорит документация – это контроллер, который показывает, что видит “камера документов”.
Добавьте его в вашу иерархию контроллеров для сканирования документов, как показано ниже:
@IBAction private func scan(_ sender: Any?) { let scannerVC = VNDocumentCameraViewController() scannerVC.delegate = self self.present(scannerVC, animated: true, completion: nil) }
также, не забудьте подписаться и реализовать делегат VNDocumentCameraViewControllerDelegate. В нем находится всего 3 метода, каждый отвечающий за состояние контроллера:
optional func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) optional func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) optional func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error)
Распознавание текста в документах
Как вы могли догадаться, показ сканера документов –– это только начало. Теперь текст нужно распознать! Для этого нам понадобится VNRecognizeTextRequest –– запрос, который будет определять место текста, а также распознавать его на картинке.
private var request: VNRecognizeTextRequest! private func setupVisionKit() { self.request = VNRecognizeTextRequest(completionHandler: { [weak self] request, error in guard let `self` = self else { return } if let error = error { print("Scanned with error: \(error.localizedDescription)") return }
guard let result = request.results as? [VNRecognizedTextObservation], result.count > 0 else { print("Nothing found") return } var scannedTextValue = "" for observation in result { guard let topValue = observation.topCandidates(1).first else { return } scannedTextValue += "\(topValue.string)\n" } DispatchQueue.main.async { self.recognizedTextView.text = scannedTextValue } }) self.request.recognitionLanguages = ["en-US"] self.request.recognitionLevel = .accurate }
Несколько слов о параметрах VNRecognizeTextRequest
В примере выше мы установили два свойства – recognitionLanguages (массив языков) и recognitionLevel (.fast – быстрый и .accurate – точный). Также существует еще несколько дополнительных опций:
- customWords – массив слов, дополняющие словари языков;
- minimumTextHeight – число от 0 до 1. Размер от высоты изображения, при котором текст не будет распознаваться;
- usesLanguageCorrection – булевое значение. Указывает на использование коррекции языка во время распознавания текста.
Запрос, который мы создали имеет комплишен, который будет запускаться каждый раз, когда нам нужно будет распознать текст с картинки.
Для каждого сканирования нам нужно запускать отдельный VNImageRequestHandler. Во избежание “подтормаживания” интерфейса обработку нужно запсукать в отдельном .userInitiated потоке.
private func recognizeText(in image: UIImage) { guard let cgImage = image.cgImage else { return } self.imageView.image = image DispatchQueue.global(qos: .userInitiated).async { [weak self] in guard let `self` = self else { return } let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:]) do { try imageRequestHandler.perform([self.request]) } catch { print(error.localizedDescription) } } }
Для лучших результатов рекомендуется использовать cgImage.
Выводы
В данной статье мы научились сканировать документы и распознавать на них текст с помощью VisionKit в iOS 13.
Финальный код доступен здесь.