【SwiftUI】Visionで色々と認識してみる
画像などからテキストやバーコード、顔、顔のランドマークを検出できるフレームワークに
Vision Framework
があります。
はじめに
Visionをインポートします。
ライブビデオなどからテキストなどを認識できるVisionKit
もありますが、今回はVisionを使用します。
import Vision
VisionKitについてはこちらで取り上げています。
実際に試してみる
1. テキスト(文字)認識
let request = VNRecognizeTextRequest { (request, error) in
if let results = request.results as? [VNRecognizedTextObservation] {
let recognizedStrings = results.compactMap { observation in
observation.topCandidates(1).first?.string
}
print(recognizedStrings)
}
}
テキストの認識をするためには、VNRecognizeTextRequest
を使用します。
画像からテキストを見つけると、認識をするようにリクエストをします。
VNRecognizedTextObservation
は、VNRecognizeTextRequestの結果や認識したテキストの内容を持っています。
let image: UIImage = "画像"
guard let cgImage = image.cgImage else {
return
}
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
DispatchQueue.global().async {
do {
try handler.perform([request])
} catch {
print(error)
}
}
リクエストを実行しています。
VNImageRequestHandler
は、リクエストを処理するためのオブジェクトです。
認識できる言語は、supportedRecognitionLanguages
を使用することで確認できます。
try! request.supportedRecognitionLanguages()
また、recognitionLanguages
を使用することで、認識したい言語に優先順位をつけることができます。
request.recognitionLanguages = ["ja-JP"]
全体のコード
テキスト認識
func textRecognition(_ image: UIImage) {
let request = VNRecognizeTextRequest { (request, error) in
if let results = request.results as? [VNRecognizedTextObservation] {
let recognizedStrings = results.compactMap { observation in
observation.topCandidates(1).first?.string
}
print(recognizedString)
}
}
request.recognitionLanguages = ["ja-JP"]
guard let cgImage = image.cgImage else {
return
}
DispatchQueue.global().async {
do {
try handler.perform([request])
} catch {
print(error)
}
}
}
2. バーコード認識
let request = VNDetectBarcodesRequest { (request, error) in
if let results = request.results as? [VNBarcodeObservation] {
let barcodes = results.compactMap { observation in
observation.payloadStringValue
}
print(barcodes)
}
}
バーコード認識では、VNDetectBarcodesRequest
を使用します。
役割は、VNRecognizeTextRequestと同様にバーコードやQRを見つけるとリクエストをします。
VNBarcodeObservation
も同様で、結果や内容を持っています。
また、supportedSymbologies
や symbologies
を使用することで、認識できるバーコードシンボルがわかります。
// サポートしているバーコードシンポル
try! request.supportedSymbologies()
// 画像から認識できるバーコードシンボル
request.symbologies
全体のコード
バーコード認識
func barkodeRecognition(_ image: UIImage) {
let request = VNDetectBarcodesRequest { (request, error) in
if let results = request.results as? [VNBarcodeObservation] {
let barcodes = results.compactMap { observation in
observation.payloadStringValue
}
print(barcodes)
}
}
guard let cgImage = image.cgImage else {
return
}
DispatchQueue.global().async {
do {
try handler.perform([request])
} catch {
print(error)
}
}
}
3. 顔認識
let request = VNDetectFaceRectanglesRequest { (request, error) in
if let error {
print(error)
return
}
request.results?.forEach({ result in
guard let observation = result as? VNFaceObservation else {
return
}
print(observation.boundingBox)
})
}
顔認識では、顔を見つけてリクエストを行うVNDetectFaceRectanglesRequest
か、
今回は使用していませんが、目や鼻、口などの特徴のリクエストを行う、VNDetectFaceLandmarksRequest
を使用します。
他のと同様に、VNFaceObservation
は 結果、内容を持っています。
全体のコード
顔認識
func faceRecognition(_ image: UIImage) {
let request = VNDetectFaceRectanglesRequest { (request, error) in
if let error {
print(error)
return
}
request.results?.forEach({ result in
guard let observation = result as? VNFaceObservation else {
return
}
print(observation.boundingBox)
})
}
guard let cgImage = image.cgImage else {
return
}
DispatchQueue.global().async {
do {
try handler.perform([request])
} catch {
print(error)
}
}
}
その他のリクエストをいくつか
VNRecognizeAnimalsRequest ... 動物を認識できます。(犬と猫しかできないみたいです。)
VNDetectHumanRectanglesRequest ... 顔だけでなく、全身を認識できます。
VNDetectRectanglesRequest ... 長方形のオブジェクトを認識できます。
最後に
テキスト認識はかなり精度がよく、日本語もひらがな、カタカナはほぼ完璧に認識してくれました。
漢字も精度はいいですが、画数が多いものは別の漢字として認識されてしまうことがありました。
また、普通のアルファベットも筆記体も少し癖が入ると正しく認識できていませんでした。
上の画像では、筆記体の「i」が「e」と認識されてしまっています。
英語を公用語にしている国では、もっと形を崩したものが多いので、手書きのものはほとんど認識できないと思います。 まぁ手書きのテキストを認識することはあまりないと思いますが。
GitHubでテキスト、バーコード、顔を認識できるアプリを公開しています。
参考にしてもらえると嬉しいです。
Discussion