Search code examples
pythonpython-imaging-librarybufferedreader

How to pass a PIL.Image as an Image stream to ComputerVisionClient read_in_stream


I'm working on a python service where I have an image provided as a PIL Image. I'm wanting to pass this image to Azure Vision using a ComputerVisionClient.

My setup is correct as I can pass in local files and URLs while testing locally and they work fine.

I'm currently trying to convert the image to a BufferedReader but the resulting call to read_in_stream ends up returning a bad request.

I end up with a BufferedReader object, but it's obviously not in the shape it needs to be.

computervision_client = ComputerVisionClient(_self.AV_LABEL_URL, CognitiveServicesCredentials(_self.AV_LABEL_SERVICE_KEY))
        
buffered = BytesIO()
image.save(buffered, format="JPEG")
buffered.mode = "rb"
buffered.name = "image.JPEG"
stream = io.BufferedReader(buffered);

results = computervision_client.read_in_stream(stream, raw = True)  

Any ideas on what I need to do to make it acceptable, or another approach to turn the PIL Image into a stream for the read_in_stream?


Solution

  • The issue I had was a I was not reset the steam back to the begining position after calling save. i.e. seek(0) The below code works.

    computervision_client = ComputerVisionClient(_self.AV_LABEL_URL, CognitiveServicesCredentials(_self.AV_LABEL_SERVICE_KEY))
    
    buffered = BytesIO()
    image.save(buffered, "JPEG")
    
    with io.BufferedReader(buffered) as image_stream:
        image_stream.seek(0) # reset the file location. The file would be at the end of the file after saving the image above.
        results = computervision_client.read_in_stream(image_stream, raw = True)  
    
    operation_location = results.headers["Operation-Location"]
    operation_id = operation_location.split("/")[-1]
    
    # Wait for the asynchronous operation to complete. This is just POC and should look at other ways to do this.
    exit = 0
    while exit < 30:
        read_results = computervision_client.get_read_result(operation_id)
        if read_results.status not in [OperationStatusCodes.running, OperationStatusCodes.not_started]:
            break
        time.sleep(1)
        exit = exit + 1