рдЖрдЬ рд╣рдо рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЛ рд╕реНрдХреИрди рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕реЗ рдорд╛рдиреНрдпрддрд╛ рдкреНрд░рд╛рдкреНрдд рдкрд╛рда рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВрдЧреЗред рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ: рд╡рд┐рдЬрд╝рдирдХрд┐рдЯ рд╕реНрдХреИрдирд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ рдФрд░ рдкрд╛рда рдкрд╣рдЪрд╛рди рдХреЗ рд▓рд┐рдП рд╡рд┐рдЬрд╝рди ред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ Xcode 11 рдФрд░ iOS 13 рд╕реНрдерд╛рдкрд┐рдд рд╣реИ , рдлрд┐рд░ рд╕реНрдЯреЛрд░реАрдмреЛрд░реНрдб рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ редрд╣рдо рд╡реАрдбрд┐рдпреЛ рдХреИрдорд░рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдХреИрди рдХрд░реЗрдВрдЧреЗред рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ NSCameraUsageDescription рдХреЛ Info.plist рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ , рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдмрд┐рдирд╛ рдпрд╣ рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рд╕реНрдХреИрдирд┐рдВрдЧ
рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдХреЛ рд╕реНрдХреИрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд┐рдЬрд╝рдирдХрд┐рдЯ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ ред рд╕реНрдХреИрдирд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░реАрди рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ 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)
}
controller.dismiss(animated: true)
}
рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрдкрд╛рда рдорд╛рдиреНрдпрддрд╛
рд╣рдордиреЗ рд╕реНрдХреИрдирд┐рдВрдЧ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛, рдЕрдм рд╣рдо рдЯреЗрдХреНрд╕реНрдЯ рдХреЛ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВредрд╕рдм рдХреБрдЫ рд╕реБрдЪрд╛рд░реВ рд░реВрдк рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдорд╛рдиреНрдпрддрд╛ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдбрд┐рд╕реНрдкреИрдЪреНрдпреВ рдмрдирд╛рдПрдВ :lazy var workQueue = {
return DispatchQueue(label: "workQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
}()
рдорд╛рдиреНрдпрддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЪрд┐рддреНрд░ рдХреЗ рд╕рд╛рде рдПрдХ VNImageRequestHandler рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдФрд░ VNRecognizeTextRequest рдХреЗ рд╕рд╛рде рд╡рд┐рдХрд▓реНрдк рдорд╛рдиреНрдпрддрд╛ , рдХрд╕реНрдЯрдорд╡рд░реНрдХ , рдорд╛рдиреНрдпрддрд╛ Languages , рд╕рд╛рде рд╣реА рдПрдХ рдкреВрд░реНрдг рд╣реИрдВрдбрд▓рд░ рдЬреЛ рдкрд╛рда рд░реВрдк рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рджреЗрдЧрд╛ред рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, рд╣рдо рд╕рд░реНрд╡реЛрддреНрддрдо рдкрд╛рда рд╡рд┐рдХрд▓реНрдк рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдПрдХрддреНрд░ рдХрд░рддреЗ рд╣реИрдВ: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)
}
}
}
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рдбреЗрд╡рд▓рдкрд░.apple.com/documentation/visionkit WWDC рднрд╛рд╖рдг рдлреНрд░реЗрдорд╡рд░реНрдХ рд╡реАрдбрд┐рдпреЛ:developer.apple.com/videos/all-videos/?q=VisionрдЧреАрдерд╣рдм рдкрд░рд┐рдпреЛрдЬрдирд╛:github -usenbekov / рджреГрд╖реНрдЯрд┐-рдбреЗрдореЛ