Я написал базовый скрипт на Python для вызова и использования GCP Vision API. Моя цель - отправить на него изображение продукта и получить (с помощью оптического распознавания символов) слова, написанные на этом поле. У меня есть предопределенный список брендов, поэтому я могу искать в тексте, возвращенном API, бренд и определять, что это такое.
Мой скрипт на Python выглядит следующим образом:
import io
from google.cloud import vision
from google.cloud.vision import types
import os
import cv2
import numpy as np
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "**************************"
def detect_text(file):
"""Detects text in the file."""
client = vision.ImageAnnotatorClient()
with io.open(file, 'rb') as image_file:
content = image_file.read()
image = types.Image(content=content)
response = client.text_detection(image=image)
texts = response.text_annotations
print('Texts:')
for text in texts:
print('\n"{}"'.format(text.description))
vertices = (['({},{})'.format(vertex.x, vertex.y)
for vertex in text.bounding_poly.vertices])
print('bounds: {}'.format(','.join(vertices)))
file_name = "Image.jpg"
img = cv2.imread(file_name)
detect_text(file_name)
На данный момент я экспериментирую со следующим изображением продукта: (разрешение 951 × 335)
Его торговая марка - Acuvue
.
Проблема в следующем. Когда я тестирую онлайн-демонстрацию GCP Cloud Vision API, я получаю следующий текстовый результат для этого изображения:
FOR ASTIGMATISM 1-DAY ACUVUE MOIST WITH LACREON™ 30 Lenses BRAND CONTACT LENSES UV BLOCKING
(Результат json для этого возвращает все вышеперечисленные слова, включая слово Acuvue
, которое имеет значение для меня, но json слишком длинный, чтобы размещать его здесь)
Таким образом, онлайн-демонстрация довольно хорошо обнаруживает текст на продукте и, по крайней мере, точно определяет слово Acuvue
(которое является брендом). Однако, когда я вызываю тот же API в моем скрипте python с тем же изображением, я получаю следующий результат:
Texts:
"1.DAY
FOR ASTIGMATISM
WITH
LACREONTM
MOIS
30 Lenses
BRAND CONTACT LENSES
UV BLOCKING
"
bounds: (221,101),(887,101),(887,284),(221,284)
"1.DAY"
bounds: (221,101),(312,101),(312,125),(221,125)
"FOR"
bounds: (622,107),(657,107),(657,119),(622,119)
"ASTIGMATISM"
bounds: (664,107),(788,107),(788,119),(664,119)
"WITH"
bounds: (614,136),(647,136),(647,145),(614,145)
"LACREONTM"
bounds: (600,151),(711,146),(712,161),(601,166)
"MOIS"
bounds: (378,162),(525,153),(528,200),(381,209)
"30"
bounds: (614,177),(629,178),(629,188),(614,187)
"Lenses"
bounds: (634,178),(677,180),(677,189),(634,187)
"BRAND"
bounds: (361,210),(418,210),(418,218),(361,218)
"CONTACT"
bounds: (427,209),(505,209),(505,218),(427,218)
"LENSES"
bounds: (514,209),(576,209),(576,218),(514,218)
"UV"
bounds: (805,274),(823,274),(823,284),(805,284)
"BLOCKING"
bounds: (827,276),(887,276),(887,284),(827,284)
Но это совсем не определяет слово "Acuvue", как это делает демо !!
Почему это происходит?
Могу ли я исправить что-то в моем скрипте Python, чтобы он работал правильно?
Спасибо за ваш комментарий. Вы имеете в виду замену detect_text(file_name)
на document_detect_text(file_name)
? Это дает мне следующую ошибку: name 'document_detect_text' is not defined
И строку response = ...
, и строку texts = ...
следует изменить с помощью метода document_text_detection
и атрибута full_text_annotation
, как показано в примере, который я связал. Я надеюсь, что более надежный детектор найдет "Acuvue", но с уверенностью, которую стандартный детектор считает слишком низкой для включения.
Это очень хорошо! Теперь он возвращает длинный json, который в конце имеет следующее: text: "FOR ASTIGMATISM\n1-DAY ACUVUE\nMOIST\nWITH\nLACREON\342\204\242\n30 Lenses\nBRAND CONTACT LENSES\nUV BLOCKING\n"
. Однако мне интересно, что в нем означают эти числа `342 \ 204 \ 242`.
Так что вы можете записать ответ и, желательно, объяснить, что было неправильным в том, что я делал, а затем я отмечу его как правильное, если ничего не изменится.
The Vision API can detect and extract text from images. There are two annotation features that support OCR:
TEXT_DETECTION detects and extracts text from any image. For example, a photograph might contain a street sign or traffic sign. The JSON includes the entire extracted string, as well as individual words, and their bounding boxes.
DOCUMENT_TEXT_DETECTION also extracts text from an image, but the response is optimized for dense text and documents. The JSON includes page, block, paragraph, word, and break information.)
Я надеялся, что веб-API на самом деле использует последнее, а затем фильтрует результаты на основе достоверности.
A DOCUMENT_TEXT_DETECTION response includes additional layout information, such as page, block, paragraph, word, and break information, along with confidence scores for each.
Во всяком случае, я надеялся (и по моему опыту), что последний метод «приложит больше усилий», чтобы найти все строки.
Я не думаю, что вы делали что-то «неправильно». Есть всего два параллельных метода обнаружения. Один (DOCUMENT_TEXT_DETECTION) более интенсивен, оптимизирован для документов (вероятно, для выпрямленных, выровненных и равномерно расположенных строк) и дает больше информации, которая может быть ненужной для некоторых приложений.
Поэтому я предложил вам изменить свой код в соответствии с Python пример здесь.
Наконец, я предполагаю, что \342\204\242
, о котором вы спрашиваете, являются экранированными восьмеричными значениями, соответствующими символам utf-8, которые, по его мнению, были обнаружены при попытке идентифицировать символ ™.
Если вы используете следующий фрагмент:
b = b"\342\204\242"
s = b.decode('utf8')
print(s)
Вы будете счастливы увидеть, что он печатает ™.
Меняется ли результат (каким-либо значимым образом) при использовании запроса
DOCUMENT_TEXT_DETECTION
вместо запросаTEXT_DETECTION
? (пример)