【问题标题】:Vision API: How to get JSON-outputVision API:如何获取 JSON 输出
【发布时间】:2018-09-04 15:06:35
【问题描述】:

我无法保存 Google Vision API 提供的输出。我正在使用 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)

输出出现在屏幕上,但我不知道如何保存它。有人有什么建议吗?

【问题讨论】:

    标签: google-api google-cloud-platform google-vision


    【解决方案1】:

    仅供以后看到这一点的任何人参考,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 不支持转换为 snake_case 名称,这在带有 preserving_proto_field_name=True 的 protobuf 中得到支持。因此,目前无法将字段名称从response['full_text_annotation'] 转换为response['fullTextAnnotation'] 对此有一个 open 关闭功能请求:googleapis/proto-plus-python#109

    注意 2:如果 x=0,google vision api 不会返回 x 坐标。如果 x 不存在,protobuf 将默认 x=0。在使用MessageToJson() 的python vision 1.0.0 中,这些x 值不包含在json 中,但现在使用python vision 2.0.0 和.To_Json() 这些值包含为x:0

    【讨论】:

    • 这是实际的解决方案。任何在将 google api 响应转换为 json 时遇到问题的人都应该看看这个。
    • 很遗憾 google-cloud-vision 2.0.0 没有简单的方法导出到 json。使用 vision_v1 代码可能没问题,但我很前卫。
    【解决方案2】:

    也许您已经能够找到解决问题的方法(如果是这样,我也邀请您将其分享为您自己帖子的答案),但无论如何,让我分享一些可能对有类似问题的其他用户有用:

    您可以使用 Python 中的 type() 函数进行检查,responsegoogle.cloud.vision_v1.types.AnnotateImageResponse type 的对象,而 labels[i]google.cloud.vision_v1.types.EntityAnnotation type。正如您尝试做的那样,它们似乎都没有任何开箱即用的实现将它们转换为 JSON,所以我相信在 labelsEntityAnnotation 的最简单方法/strong> 是将它们转换为 Python 字典,然后将它们全部分组到一个数组中,然后将其转换为 JSON。

    为此,我在您的 sn-p 中添加了一些简单的代码行:

    [...]
    
    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)
    

    【讨论】:

    • 谢谢你提醒我 :) 我确实找到了答案,现在发布了。
    【解决方案3】:

    有一个谷歌发布的库

    from google.protobuf.json_format import MessageToJson
    

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

    【讨论】:

    • 知道如何将其解析回 Message 吗?
    • 好的,我会检查的
    【解决方案4】:

    我能够使用以下函数保存输出:

    # 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,
                            }]
                }]
            })
    

    【讨论】:

      【解决方案5】:

      当前 Vision 库中的对象缺少序列化函数(尽管这是个好主意)。

      值得注意的是,他们即将发布一个完全不同的 Vision 库(它现在位于 Master of vision 的 repo 中,虽然尚未发布到 PyPI),这将是可能的。请注意,这是一个向后不兼容的升级,因此会有一些(希望不会太多)转换工作。

      该库返回纯 protobuf 对象,可以使用以下方法将其序列化为 JSON:

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

      你也可以使用protobuf3-to-dict之类的东西

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-19
        • 2017-11-03
        • 2020-09-18
        • 2017-12-03
        • 1970-01-01
        • 2020-04-12
        • 1970-01-01
        相关资源
        最近更新 更多