Search code examples
google-apigoogle-cloud-platformgoogle-vision

Vision API: How to get JSON-output


I'm having trouble saving the output given by the Google Vision API. I'm using Python and testing with a demo image. I get the following error:

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

Code that I executed:

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)

the output appears on the screen, however I do not know exactly how I can save it. Anyone have any suggestions?


Solution

  • FYI to anyone seeing this in the future, google-cloud-vision 2.0.0 has switched to using proto-plus which uses different serialization/deserialization code. A possible error you can get if upgrading to 2.0.0 without changing the code is:

    object has no attribute 'DESCRIPTOR'
    

    Using google-cloud-vision 2.0.0, protobuf 3.13.0, here is an example of how to serialize and de-serialize (example includes json and 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'])
    

    Note 1: proto-plus doesn't support converting to snake_case names, which is supported in protobuf with preserving_proto_field_name=True. So currently there is no way around the field names being converted from response['full_text_annotation'] to response['fullTextAnnotation'] There is an open closed feature request for this: googleapis/proto-plus-python#109

    Note 2: The google vision api doesn't return an x coordinate if x=0. If x doesn't exist, the protobuf will default x=0. In python vision 1.0.0 using MessageToJson(), these x values weren't included in the json, but now with python vision 2.0.0 and .To_Json() these values are included as x:0