Оптическое распознавание символов (OCR) Оптическое распознавание, в просторечии, заключается в распознавании текста на картинке, такого как идентификационный номер, имя, адрес и т. д. на удостоверении личности, номер карты на банковской карте и т. д.
Evil
Evil
ЯвляетсяiOS
иmacOS
Простая структура идентификации под платформой. поддержка черезCocoaPods,CarthageиSwift Package ManagerУстановить. Базовую модель распознавания можно легко перенести на другие платформы.
Основной процесс распознавания OCR
- Захватите область, которую нужно выделить, из всего изображения
eg: 从一整张图片中截取身份证所在的矩形区域
- Захват текстовой области
eg: 通过一定的算法截取到身份证号码所在的区域
- Выполните серию предварительной обработки в текстовой области, чтобы облегчить следующую операцию.
eg: 高斯模糊、膨胀等等
- Разделить текст, текстовая область разделена на единуюХарактер
- поставить сингл
字
Добавьте распознавание нейронной сети
Evil
использовать последнююVisionрамки для достижения.первые 4 шагаApple предоставляет нам хороший системный метод, например:VNDetectTextRectanglesRequest
. Так что здесь мы не обсуждаемпервые 4 шагаНекоторые детали реализации, если вы хотите узнать, как использовать API, вы можете увидетьздесь.
Как распознавать отдельные слова с помощью нейронных сетей
Я лично считаю, что с распознаванием небольшого количества печатного текста может справиться модель классификации изображений.Если у вас есть лучшее решение, добро пожаловать в общение. если выCNN调参侠
Тогда следующий контент легко понять, но если вы не神经网络
Соответствующие базовые знания, следующее содержание может быть немного неясным, потому что, в конце концов, я знаю только мех~. Если у вас раньше не было соответствующих знаний, вы можете узнать о том, что Apple предоставляет нам.Turi Create, вы можете не проектировать сеть самостоятельно.
0x00 Проектная сеть
Во-первых, нам нужно спроектировать сеть CNN для ввода нашего изображения одного слова и позволить ему распознать его.Поскольку наша задача распознавания очень проста, архитектура сети будет очень простой. Ниже приведеныKeras (2.0.6)
Код:
model = Sequential()
model.add(Conv2D(32, (5, 5), input_shape=(28, 28, 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(128, (1, 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
0x01 Сгенерировать обучающие данные
Мы знаем, что для обучения сети нам нужно много необработанных данных, так что, если у нас их нет? Некоторые учебные ресурсы можно найти в Интернете, но что, если мы хотим определить здесь идентификационный номер?
Конечно, это генерируется путем написания скриптов.Например, мы будем генерировать много-много身份证号码区域
. Внесите некоторые случайные изменения, чтобы увеличить разнообразие данных.
o_image = Image.open(BACKGROUND)
draw_brush = ImageDraw.Draw(o_image)
font_size = random.randint(-5, 5) + 35
draw_brush.text((10 + random.randint(-10, 10), 15 + random.randint(-2, 2)), LABELS,
fill='black',
font=ImageFont.truetype(FONT, font_size))
o_image = ImageEnhance.Color(o_image).enhance(
random.uniform(0.5, 1.5)) # 着色
o_image = ImageEnhance.Brightness(o_image).enhance(
random.uniform(0.5, 1.5)) # 亮度
o_image = ImageEnhance.Contrast(o_image).enhance(
random.uniform(0.5, 1.5)) # 对比度
o_image = ImageEnhance.Sharpness(o_image).enhance(
random.uniform(0.5, 1.5)) # 旋转
o_image = o_image.rotate(random.randint(-2, 2))
o_image.save(output + '/%d.png' % idx)
После того, как у вас есть текстовая область, вам нужно сегментировать текстовую область на отдельные слова, а затем обучить сеть.Поскольку следующая задача универсальна, я просто написал небольшой инструмент под названиемPrepareBot
. Конкретный код находится вздесь, Вы можете пойти и посмотреть, если вы заинтересованы.
0x02 Обучить сеть
С данными, с моделью сети очень просто обучить сеть следующим образом:
model.fit_generator(generator=train_data_generator)
Хорошо, вот, давайте понаблюдаем за сходимостью и точностью распознавания сети.Если не очень плохо, то можно поставить вот этоmodel
Сохраните его и подготовьтесь к будущим задачам идентификации. Обратите внимание, что этот шаг генерируетKeras model
Он кроссплатформенный, то есть его можно использовать для идентификации в Windows, Linux и даже Android.
0x03 Преобразовать сеть
На предыдущих шагах мы создалиKeras
сетевая модель, какEvil
где использовать эти модели? Сначала нам нужно использовать инструменты, предоставляемые Applecoremltools, преобразуйте модель keras вCoreModel
Конкретное использование примерно следующее
# Prepare model for inference
for k in model.layers:
if type(k) is keras.layers.Dropout:
model.layers.remove(k)
model.save("./temp.model")
core_ml_model = coremltools.converters.keras.convert("./temp.model",
input_names='image',
image_input_names='image',
output_names='output',
class_labels=list(labels),
image_scale=1 / 255.)
core_ml_model.author = 'gix.evil'
core_ml_model.license = 'MIT license'
core_ml_model.short_description = 'model to classify chinese IDCard numbers'
core_ml_model.input_description['image'] = 'Grayscale image of card number'
core_ml_model.output_description['output'] = 'Predicted digit'
core_ml_model.save('demo.mlmodel')
спастиdemo.mlmodel
резервное копирование файлов.
0x04 сеть импорта
У нас есть файл модели, как импортироватьEvil
Что с рамкой?
Перетащите прямо в xcode
Существенным недостатком этого метода является то, что он увеличит размер приложения, поэтому мы не рекомендуем использовать этот метод. Но на этот раз это всегда самый простой способ для вас во время нашей отладки.
Загрузка во время выполнения
Этот метод не влияет на размер приложения, но все также заметили, что файл модели нужно загружать во время выполнения, и сложность кода возрастет, но хорошая новость заключается в том, чтоEvil
Очень дружеская поддержка для этого. Вам просто нужно сохранить файлы модели на вашем собственном сервере или CDN, а затемinfo.plist
Настройте путь загрузки в файлеEvil
Вы можете автоматически настроить свою сетевую модель.
0x05 использовать сеть
Все готово, как им пользоваться? Просто выполните шаги 1-5, которые мы перечислили ранее, и вызовите их по очереди.Evil
Предоставляемый интерфейс подойдет. Например
// 1. Используйте встроенную модель Evil для определения идентификационных номеров
lazy var evil = try? Evil(recognizer: .chineseIDCard)
let image: Recognizable = ....
let cardNumber = self.evil?.recognize(image)
print(cardNumber)
// 2. Используйте пользовательскую модель
let url: URL = ...
let evil = try? Evil(contentsOf: url, name: "demo")
let ciimage = CIImage(cvPixelBuffer: pixelBuffer).oriented(orientation)
if let numbers = ciimage.preprocessor
// 透视矫正
.perspectiveCorrection(boundingBox: observation.boundingBox,
topLeft: observation.topLeft,
topRight: observation.topRight,
bottomLeft: observation.bottomLeft,
bottomRight: observation.bottomRight)
.mapValue({Value($0.image.oriented(orientation), $0.bounds)})
// 保证身份证头像朝上
.correctionByFace()
// 截取号码区域
.cropChineseIDCardNumberArea()
// 预处理 高斯模糊等
.process()
// 分割文字
.divideText()
// 简单校验
.value?.map({ $0.image }), numbers.count == 18 {
if let result = try? self.evil?.prediction(numbers) {
if let cardnumber = result?.flatMap({ $0 }).joined() {
DispatchQueue.main.async {
self.tipLabel.text = cardnumber
}
}
}
}
Суммировать
Хорошая, хорошая реклама здесь, приветствую всех, кто жалуется, добро пожаловатьstar
fork
, Добро пожаловать вpr
, вы можете предоставить свои собственные обученные модели. Впервые пишу статью в Наггетс, спасибо за поддержку.