Существует несколько пакетов с открытым исходным кодом, которые могут обнаруживать текст на зашумленных фоновых изображениях, сравнимых с Google Vision API.
Вы можете использовать простую архитектуру Fixed Convolution Layer, называемую EAST (Efficient and Accurate SceneДетектор текста) Zhou et al.https://arxiv.org/abs/1704.03155v2
Использование Python:
Загрузите предварительно обученную модель из: https://www.dropbox.com/s/r2ingd0l3zt8hxs/frozen_east_text_detection.tar.gz?dl=1 .Извлеките модель в вашу текущую папку.
Вам понадобится OpenCV> = 3.4.2 для выполнения следующих команд.
import cv2
import math
net = cv2.dnn.readNet("frozen_east_text_detection.pb") #This is the model we get after extraction
frame = cv2.imread(<image_filename>)
inpWidth = inpHeight = 320 # A default dimension
# Preparing a blob to pass the image through the neural network
# Subtracting mean values used while training the model.
image_blob = cv2.dnn.blobFromImage(frame, 1.0, (inpWidth, inpHeight), (123.68, 116.78, 103.94), True, False)
Теперь нам нужно определить выходные слои, которые производятсяпозиционные значения обнаруженного текста и его достоверность Оценка (с помощью сигмоидальной функции)
output_layer = []
output_layer.append("feature_fusion/Conv_7/Sigmoid")
output_layer.append("feature_fusion/concat_3")
Наконец, мы сделаем прямое распространение по сети, чтобы получить желаемый результат.
net.setInput(image_blob)
output = net.forward(output_layer)
scores = output[0]
geometry = output[1]
Здесь я использовал функцию декодирования, определенную на странице github opencv, https://github.com/opencv/opencv/blob/master/samples/dnn/text_detection.py, чтобы преобразовать позиционные значения в координаты блока.(строки с 23 по 75).
Для порога обнаружения ящика я использовал значение 0,5, а для немакс. подавления - 0,3.Вы можете попробовать разные значения, чтобы получить лучшие ограничивающие рамки.
confThreshold = 0.5
nmsThreshold = 0.3
[boxes, confidences] = decode(scores, geometry, confThreshold)
indices = cv2.dnn.NMSBoxesRotated(boxes, confidences, confThreshold, nmsThreshold)
Наконец, для наложения полей на обнаруженный текст на изображении:
height_ = frame.shape[0]
width_ = frame.shape[1]
rW = width_ / float(inpWidth)
rH = height_ / float(inpHeight)
for i in indices:
# get 4 corners of the rotated rect
vertices = cv2.boxPoints(boxes[i[0]])
# scale the bounding box coordinates based on the respective ratios
for j in range(4):
vertices[j][0] *= rW
vertices[j][1] *= rH
for j in range(4):
p1 = (vertices[j][0], vertices[j][1])
p2 = (vertices[(j + 1) % 4][0], vertices[(j + 1) % 4][1])
cv2.line(frame, p1, p2, (0, 255, 0), 3)
# To save the image:
cv2.imwrite("maggi_boxed.jpg", frame)

Я не экспериментировалс разными значениями порога.Их изменение, несомненно, даст лучший результат, а также устранит неправильную классификацию логотипа в виде текста.
Примечание. Модель была обучена английскому корпусу, поэтому слова на хинди не будут обнаружены.Также вы можете прочитать документ с описанием наборов тестовых данных, на которых он был отмечен.