Vision API: как получить JSON-вывод

У меня возникли проблемы с сохранением выходных данных API Google Vision. Я использую Python и тестирую демонстрационное изображение. Я получаю следующую ошибку:

TypeError: [mid:...] + is not JSON serializable

Код, который я выполнил:

import io
import os
import json
# Imports the Google Cloud client library
from google.cloud import vision
from google.cloud.vision import types

# Instantiates a client
vision_client = vision.ImageAnnotatorClient()


# The name of the image file to annotate
file_name = os.path.join(
    os.path.dirname(__file__),
    'demo-image.jpg') # Your image path from current directory

# Loads the image into memory
with io.open(file_name, 'rb') as image_file:
    content = image_file.read()
    image = types.Image(content=content)

# Performs label detection on the image file
response = vision_client.label_detection(image=image)
labels = response.label_annotations


print('Labels:')
for label in labels:
    print(label.description, label.score, label.mid)

with open('labels.json', 'w') as fp:
   json.dump(labels, fp)

вывод появляется на экране, однако я точно не знаю, как его сохранить. У кого-нибудь есть предложения?


person Bruna B    schedule 04.09.2018    source источник


Ответы (5)


К сведению всех, кто увидит это в будущем, google-cloud-vision 2.0.0 переключился на использование proto-plus, который использует другой код сериализации/десериализации. Возможная ошибка, которую вы можете получить при обновлении до версии 2.0.0 без изменения кода:

object has no attribute 'DESCRIPTOR'

Используя google-cloud-vision 2.0.0, protobuf 3.13.0, вот пример сериализации и десериализации (пример включает json и protobuf)

import io, json
from google.cloud import vision_v1
from google.cloud.vision_v1 import AnnotateImageResponse

with io.open('000048.jpg', 'rb') as image_file:
    content = image_file.read()

image = vision_v1.Image(content=content)
client = vision_v1.ImageAnnotatorClient()
response = client.document_text_detection(image=image)

# serialize / deserialize proto (binary)
serialized_proto_plus = AnnotateImageResponse.serialize(response)
response = AnnotateImageResponse.deserialize(serialized_proto_plus)
print(response.full_text_annotation.text)

# serialize / deserialize json
response_json = AnnotateImageResponse.to_json(response)
response = json.loads(response_json)
print(response['fullTextAnnotation']['text'])

Примечание 1: proto-plus не поддерживает преобразование имен в змеиный регистр, которое поддерживается в protobuf с preserving_proto_field_name=True. Таким образом, в настоящее время нет способа обойти преобразование имен полей из response['full_text_annotation'] в response['fullTextAnnotation']. Для этого существует закрытый запрос функции open: googleapis/proto-plus-python#109

Примечание 2. API-интерфейс Google Vision не возвращает координату X, если x=0. Если x не существует, protobuf по умолчанию примет x=0. В python vision 1.0.0 с использованием MessageToJson() эти значения x не были включены в json, но теперь с python vision 2.0.0 и .To_Json() эти значения включены как x:0

person Alex Mann    schedule 14.01.2021
comment
Это фактическое решение. Любой, у кого есть проблемы с преобразованием ответа Google API в json, должен просто посмотреть на это. - person Maaz Bin Musa; 16.03.2021
comment
Жаль, что в google-cloud-vision 2.0.0 нет простого способа экспорта в json. Вероятно, можно использовать код vision_v1, но я нервничаю. - person yangliu2; 27.03.2021

Возможно, вы уже смогли найти решение своей проблемы (если это так, я приглашаю вас поделиться им и в качестве ответа на свой собственный пост), но в любом случае позвольте мне поделиться некоторыми заметками, которые могут быть полезны для другие пользователи с похожей проблемой:

Как вы можете проверить с помощью функции type() в Python, response является объектом google.cloud.vision_v1.types.AnnotateImageResponse type, а labels[i] является объектом google.cloud.vision_v1.types.EntityAnnotation тип. Кажется, ни у одного из них нет какой-либо готовой реализации для преобразования их в JSON, как вы пытаетесь сделать, поэтому я считаю, что самый простой способ преобразовать каждый из EntityAnnotation в labels будет превратить их в словари Python, затем сгруппировать их все в массив и преобразовать в JSON.

Для этого я добавил несколько простых строк кода в ваш фрагмент:

[...]

label_dicts = [] # Array that will contain all the EntityAnnotation dictionaries

print('Labels:')
for label in labels:
    # Write each label (EntityAnnotation) into a dictionary
    dict = {'description': label.description, 'score': label.score, 'mid': label.mid}

    # Populate the array
    label_dicts.append(dict) 

with open('labels.json', 'w') as fp:
   json.dump(label_dicts, fp)
person dsesto    schedule 12.12.2018
comment
Спасибо, что напомнили мне :) Я нашел ответ и теперь опубликовал. - person Bruna B; 19.12.2018

Существует библиотека, выпущенная Google

from google.protobuf.json_format import MessageToJson

webdetect = vision_client.web_detection(blob_source) jsonObj = MessageToJson(webdetect)

person Robert Robinson    schedule 03.04.2019
comment
Любая идея, как разобрать его обратно в Message ? - person Jimmar; 17.12.2019
comment
Хорошо, я проверю это - person Robert Robinson; 24.12.2019

Мне удалось сохранить вывод с помощью следующей функции:

# Save output as JSON
def store_json(json_input):
    with open(json_file_name, 'a') as f:
        f.write(json_input + '\n')

И, как упомянул @dsesto, мне пришлось определить словарь. В этом словаре я определил, какие типы информации я хотел бы сохранить в своем выводе.

with open(photo_file, 'rb') as image:
    image_content = base64.b64encode(image.read())
    service_request = service.images().annotate(
        body={
            'requests': [{
                'image': {
                    'content': image_content
                },
                'features': [{
                    'type': 'LABEL_DETECTION',
                    'maxResults': 20,
                },
                    {
                        'type': 'TEXT_DETECTION',
                        'maxResults': 20,
                    },
                        {
                            'type': 'WEB_DETECTION',
                            'maxResults': 20,
                        }]
            }]
        })
person Bruna B    schedule 19.12.2018

У объектов в текущей библиотеке Vision отсутствуют функции сериализации (хотя это хорошая идея).

Стоит отметить, что они собираются выпустить существенно другую библиотеку для Vision (сейчас она находится в репозитории master of vision, хотя еще не выпущена для PyPI), где это будет возможно. Обратите внимание, что это обновление несовместимо с предыдущими версиями, поэтому потребуются некоторые (надеюсь, не слишком большие) усилия по преобразованию.

Эта библиотека возвращает простые объекты protobuf, которые можно сериализовать в JSON, используя:

from google.protobuf.json_format import MessageToJson
serialized = MessageToJson(original)

Вы также можете использовать что-то вроде protobuf3-to-dict.

person shril    schedule 20.12.2018