Мы рассмотрим, как использовать машинное обучение для обнаружения и определения местоположения текста на изображении с помощью фреймворка Vision. Фреймворк Vision может гораздо больше, чем просто поиск текста на изображении. Он также способен изолировать определённые области на изображениях, отслеживать объекты в последовательности изображений, определять положение рук и тела и многое другое.
Если вы работали над проектами, связанными со сканированием QR- или штрихкодов, скорее всего, вы уже использовали Vision, возможно, даже не осознавая этого. Лично я впервые столкнулся с Vision, когда создал консольную утилиту на Swift для удаления фона с изображений.
Создание распознавателя текста
Давайте начнём с изучения того, как использовать ML-фреймворк Vision от Apple для извлечения текста из изображений.
Для начала настроим компонент распознавания текста:
import Foundation
import SwiftUI
import Vision
struct TextRecognizer {
var recognizedText = ""
var observations: [RecognizedTextObservation] = []
init(imageResource: ImageResource) async {
// Create a RecognizeTextRequest.
var request = RecognizeTextRequest()
// Set the request's recognitionLevel to .accurate.
request.recognitionLevel = .accurate
// Create a UIImage using the ImageResource.
let image = UIImage(resource: imageResource)
// Convert the UIImage to Data.
if let imageData = image.pngData(),
// The perform request can fail
// so use try? to proceed only when results are available.
let results = try? await request.perform(on: imageData) {
// Store the observations that are returned by the RecognizeTextRequest.
observations = results
}
// Iterate through the observations
// and get the top candidate of the potential text values.
for observation in observations {
let candidate = observation.topCandidates(1)
if let observedText = candidate.first?.string {
recognizedText += "\n\(observedText) "
}
}
}
}
Вот краткий обзор того, что делает этот код:
- Импортирует фреймворки SwiftUI и Vision
- Создает
RecognizeTextRequest, который является частью инструментов Vision для распознавания текста на изображениях. - Преобразует
UIImageвData. Этот шаг необходим, посколькуRecognizeTextRequestработает с данными, а не с типами изображений Swift, такими какUIImage. - Использует метод
performобъекта текстового запроса для анализа изображения и сбора результатов. Поскольку это требует асинхронной обработки, функция инициализации должна быть помечена какasyncдля корректного ожидания результата. - Сохраняет наблюдения, возвращаемые
RecognizeTextRequest. - Проходит по наблюдениям и получает наиболее подходящий вариант потенциального текстового значения.
- Всякий раз, когда распознанный текст найден, добавляет его к локальному свойству.
Вот как мы можем интегрировать его в представление SwiftUI:
import SwiftUI
struct TextRecognitionView: View {
let imageResource: ImageResource
@State private var textRecognizer: TextRecognizer?
var body: some View {
List {
Section {
Image(imageResource)
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.listRowBackground(Color.clear)
Section {
Text(textRecognizer?.recognizedText ?? "")
} header: {
Text("Identified text from image")
}
}
.navigationTitle("Text Recognition")
.task {
// The initializer is async
// so you need to call it from an async function or a task.
textRecognizer = await TextRecognizer(imageResource: imageResource)
}
}
}
Ниже представлен скриншот, демонстрирующий эту функцию в действии:
Выделение найденного текста
Теперь, когда мы определили текст на изображении, следующим шагом будет его визуальное выделение путем рисования прямоугольников вокруг обнаруженных текстовых областей.
Для этого мы начнём с определения структуры, представляющей собой форму, которую можно нарисовать.
import Foundation
import SwiftUI
import Vision
struct BoundsRect: Shape {
let normalizedRect: NormalizedRect
func path(in rect: CGRect) -> Path {
// Convert the normalized coordinates to the coordinates of the image.
let imageCoordinatesRect = normalizedRect
.toImageCoordinates(rect.size, origin: .upperLeft)
return Path(imageCoordinatesRect)
}
}
Вот краткий обзор того, что делает код:
- Соответствие протоколу
Shape. - Импортирует фреймворк Vision и определяет свойство
NormalizedRect. Каждое распознанное текстовое наблюдение включает данные о местоположении, указывающие, где текст был обнаружен на изображении. - Преобразует нормализованные координаты в координаты изображения.
Затем в представлении SwiftUI мы можем добавить оверлей к изображению, чтобы нарисовать фигуры BoundsRect вокруг каждого блока распознанного текста.
Вот как это можно сделать:
struct TextRecognitionView: View {
[...]
let boundingColor = Color(red: 0.31, green: 0.11, blue: 0.11)
var body: some View {
List {
Section {
Image(imageResource)
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 8))
.overlay {
if let observations = textRecognizer?.observations {
ForEach(observations, id: \.uuid) { observation in
// Draw a BoundsRect around
// each text item observed in the image.
BoundsRect(normalizedRect: observation.boundingBox)
.stroke(boundingColor, lineWidth: 3)
}
}
}
}
[...]
}
}
}
Ниже представлен скриншот, демонстрирующий функцию выделения текста в действии:
Заключение
Фреймворк Vision — это мощный и универсальный инструмент, способный не только находить текст на изображении. Он также способен изолировать определённые области на изображениях, отслеживать объекты в последовательности изображений, определять положение рук и тела и многое другое.
В этой статье вы узнали, как использовать встроенные функции Vision для обнаружения и определения местоположения текста на изображениях. Это послужит хорошей отправной точкой для расширения возможностей распознавания текста за счёт внедрения более продвинутых функций.

