LukeMSki
LukeMSki

Reputation: 11

How to use images from Azure Functions Blob Trigger with Form Recognizer

I am trying to use Azure Functions to wrap an application using Form-Recognizer written in Python. My issue is getting a JPEG using the BlobTrigger into a format that the Form-Recognizer can work with.

The basic code for opening the image is

from PIL import Image
from io import BytesIO 
import azure.functions as func

def main(blobin: func.InputStream, blobout: func.Out[bytes], context: func.Context):
image = Image.open(blobin)

The image has class class: 'PIL.JpegImagePlugin.JpegImageFile'.

The code for calling the Form-Recognizer analyze is as follows:

base_url = r"<url>" + "/formrecognizer/v1.0-preview/custom"
model_id = "<model-id>"
headers = {
    'Content-Type': 'image/jpeg',
     'Ocp-Apim-Subscription-Key': '<subscription-key>',
}
resp = None
try:
    url = base_url + "/models/" + model_id + "/analyze" 
    resp = http_post(url = url, data = image, headers = headers)
    print("Response status code: %d" % resp.status_code)    
except Exception as e:
    print(str(e))

Unfortunately, the data = image in the http_post needs to be class: 'bytes'.

So, I tried various ways using PIL to convert the input image to a byte format.

My two main approaches were

with BytesIO() as output:
    with Image.open(input_image) as img:
    img.save(output, 'JPEG')
    image = output.getvalue()

and

image = Image.open(input_image)
imgByteArr = io.BytesIO()
image.save(imgByteArr, format='JPEG')
imgByteArr = imgByteArr.getvalue()

Both of these approaches give me a byte format, however, it still doesn't work. Either way, I end up with this response:

{'error': {'code': '2018', 'innerError': {'requestId': '8cff8e76-c11a-4893-8b5d-33d11f7e7646'}, 'message': 'Content parsing error.'}}

Does anyone know the right way to approach this problem?

Upvotes: 1

Views: 2666

Answers (1)

Peter Pan
Peter Pan

Reputation: 24138

According to the source code blob.py for the class func.InputStream from GitHub repo Azure/azure-functions-python-library, you can directly get the image bytes from the blobin variable of func.InputStream class via its read function, as the figure below.

enter image description here

Meanwhile, refer to the document Form Recognizer API, the Content-Type header should be multipart/form-data.

So I changed the offical sample code to use in Azure Function as below.

import http.client, urllib.request, urllib.parse, urllib.error, base64
import azure.functions as func

headers = {
    # Request headers
    'Content-Type': 'multipart/form-data',
    'Ocp-Apim-Subscription-Key': '{subscription key}',
}

params = urllib.parse.urlencode({
    # Request parameters
    'keys': '{string}',
})

def main(blobin: func.InputStream):
    body = blobin.read()
    try:
        conn = http.client.HTTPSConnection('westus2.api.cognitive.microsoft.com')
        conn.request("POST", "/formrecognizer/v1.0-preview/custom/models/{id}/analyze?%s" % params, body, headers)
        response = conn.getresponse()
        data = response.read()
        print(data)
        conn.close()
    except Exception as e:
        print("[Errno {0}] {1}".format(e.errno, e.strerror))

Please don't use any Python 2 functions in Azure Functions which only support Python 3.6.

Upvotes: 1

Related Questions