Converting a Vision VNTextObservation to a String
Apple finally updated Vision to do OCR. Open a playground and dump a couple of test images in the Resources folder. In my case, I called them "demoDocument.jpg" and "demoLicensePlate.jpg".
The new class is called VNRecognizeTextRequest
. Dump this in a playground and give it a whirl:
import Vision
enum DemoImage: String {
case document = "demoDocument"
case licensePlate = "demoLicensePlate"
}
class OCRReader {
func performOCR(on url: URL?, recognitionLevel: VNRequestTextRecognitionLevel) {
guard let url = url else { return }
let requestHandler = VNImageRequestHandler(url: url, options: [:])
let request = VNRecognizeTextRequest { (request, error) in
if let error = error {
print(error)
return
}
guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
for currentObservation in observations {
let topCandidate = currentObservation.topCandidates(1)
if let recognizedText = topCandidate.first {
print(recognizedText.string)
}
}
}
request.recognitionLevel = recognitionLevel
try? requestHandler.perform([request])
}
}
func url(for image: DemoImage) -> URL? {
return Bundle.main.url(forResource: image.rawValue, withExtension: "jpg")
}
let ocrReader = OCRReader()
ocrReader.performOCR(on: url(for: .document), recognitionLevel: .fast)
There's an in-depth discussion of this from WWDC19
How do I extract specific text from an image using a UITextField in Swift?
You should watch the latest WWDC on Vision framework. Basically, from iOS 13
the VNRecognizeTextRequest returns the text and also the bounding box of the text in the image.
The code can be something like this:
func startTextDetection() {
let request = VNRecognizeTextRequest(completionHandler: self.detectTextHandler)
request.recognitionLevel = .fast
self.requests = [request]
}
private func detectTextHandler(request: VNRequest, error: Error?) {
guard let observations = request.results as? [VNRecognizedTextObservation] else {
fatalError("Received invalid observations")
}
for lineObservation in observations {
guard let textLine = lineObservation.topCandidates(1).first else {
continue
}
let words = textLine.string.split{ $0.isWhitespace }.map{ String($0)}
for word in words {
if let wordRange = textLine.string.range(of: word) {
if let rect = try? textLine.boundingBox(for: wordRange)?.boundingBox {
// here you can check if word == textField.text
// rect is in image coordinate space, normalized with origin in the bottom left corner
}
}
}
}
}
Detect if face is within a circle
I have also done similar project for fun. Link here: https://github.com/sawin0/FaceDetection
For those who don't want to dive into repo.
I have quick suggestion for you, if you have path of circle and face as CGPath then you can compare circle's and face's bounding box using contains(_:using:transform:)
.
Here is a code snippet
let circleBox = circleCGPath.boundingBox
let faceBox = faceRectanglePath.boundingBox
if(circleBox.contains(faceBox)){
print("face is inside the circle")
}else{
print("face is outside the circle")
}
I hope this helps you and others too.
P.S. If there is any better way to do this then please feel free to share.
Convert Vision boundingBox from VNFaceObservation to rect to draw on image
You have to do the transition and scale according to the image.
Example
func drawVisionRequestResults(_ results: [VNFaceObservation]) {
print("face count = \(results.count) ")
previewView.removeMask()
let transform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -self.view.frame.height)
let translate = CGAffineTransform.identity.scaledBy(x: self.view.frame.width, y: self.view.frame.height)
for face in results {
// The coordinates are normalized to the dimensions of the processed image, with the origin at the image's lower-left corner.
let facebounds = face.boundingBox.applying(translate).applying(transform)
previewView.drawLayer(in: facebounds)
}
}
Related Topics
Enterprise Deployment Certificate and Profiles
Disable the Interactive Dismissal of Presented View Controller
How to Pop Two Views at Once from a Navigation Controller
How to Change Label Constraints During Runtime
How to Get All Enum Values as an Array
Notify Watchkit App of an Update Without the Watch App Requesting It
Profile Doesn't Match the Entitlements File's Value for the Application-Identifier Entitlement
Problems with Ssl Pinning and Afnetworking 2.5.0 (Nsurlerrordomain Error -1012.)
Populating Tableview with Multiple Sections and Multiple Dictionary in an Array in Swift
Ios- How to Integrate Push Notification in iOS 10
Update a Label Through Button from Different View
Over the Air (Ota) iOS IPA File Distribution for Public
How to Change Height of Grouped Uitableview Header
Xcode 11 Debugger Is Extremely Slow - a Known Problem
What Happens with Constraints When a View Is Removed
iOS Tesseract Ocr Image Preperation
How to Add Textfield to Uialertcontroller in Swift
Xcode Info.Plist Build Variable ${Product_Name:Rfc1034Identifier} Seems Completely Undocumented