2

I'm using the Azure CV module to process images, so far I have only used local images or images freely available on the web. But now I need to use the images I have stored in a storage account container.

I don't see how to do this in the documentation, E.G: this code allow to use local images:

import os
import sys
import requests
# If you are using a Jupyter notebook, uncomment the following line.
# %matplotlib inline
import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO

# Add your Computer Vision subscription key and endpoint to your environment variables.
if 'COMPUTER_VISION_SUBSCRIPTION_KEY' in os.environ:
    subscription_key = os.environ['COMPUTER_VISION_SUBSCRIPTION_KEY']
else:
    print("\nSet the COMPUTER_VISION_SUBSCRIPTION_KEY environment variable.\n**Restart your shell or IDE for changes to take effect.**")
    sys.exit()

if 'COMPUTER_VISION_ENDPOINT' in os.environ:
    endpoint = os.environ['COMPUTER_VISION_ENDPOINT']

analyze_url = endpoint + "vision/v3.0/analyze"

# Set image_path to the local path of an image that you want to analyze.
# Sample images are here, if needed:
# https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/ComputerVision/Images
image_path = "C:/Documents/ImageToAnalyze.jpg"

# Read the image into a byte array
image_data = open(image_path, "rb").read()
headers = {'Ocp-Apim-Subscription-Key': subscription_key,
           'Content-Type': 'application/octet-stream'}
params = {'visualFeatures': 'Categories,Description,Color'}
response = requests.post(
    analyze_url, headers=headers, params=params, data=image_data)
response.raise_for_status()

# The 'analysis' object contains various fields that describe the image. The most
# relevant caption for the image is obtained from the 'description' property.
analysis = response.json()
print(analysis)
image_caption = analysis["description"]["captions"][0]["text"].capitalize()

# Display the image and overlay it with the caption.
image = Image.open(BytesIO(image_data))
plt.imshow(image)
plt.axis("off")
_ = plt.title(image_caption, size="x-large", y=-0.1)
plt.show()

This other to use images from the web:

computervision_client = ComputerVisionClient(endpoint, CognitiveServicesCredentials(subscription_key))

remote_image_url = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/landmark.jpg"


'''
Describe an Image - remote
This example describes the contents of an image with the confidence score.
'''
print("===== Describe an image - remote =====")
# Call API
description_results = computervision_client.describe_image(remote_image_url )

# Get the captions (descriptions) from the response, with confidence level
print("Description of remote image: ")
if (len(description_results.captions) == 0):
    print("No description detected.")
else:
    for caption in description_results.captions:
        print("'{}' with confidence {:.2f}%".format(caption.text, caption.confidence * 100))

And this other to read data from a storage container:

from azure.storage.blob import BlobClient

blob = BlobClient.from_connection_string(conn_str="my_connection_string", container_name="my_container", blob_name="my_blob")

with open("./BlockDestination.txt", "wb") as my_blob:
    blob_data = blob.download_blob()
    blob_data.readinto(my_blob)

But I don't see how to make the connection between the storage container and the CV service

Luis Ramon Ramirez Rodriguez
  • 9,591
  • 27
  • 102
  • 181
  • How are your images stored in your Blob? After you download the contents of the blob, you will then have to retrieve your image from those contents, then convert the image to raw bytes. After you do that you should be able to send it to CV using your first script. – Tyson Jul 16 '20 at 06:56
  • @Tyson The images are in JPG format, I will prefer to not download the images to my machine before sending them to the CV API; Just read them from CV API, is that possible? – Luis Ramon Ramirez Rodriguez Jul 16 '20 at 14:47
  • 1
    Yeah, that would certainly be the best way to do it. It sounds like it should be possible, but I don't know how and couldn't find any documentation on how to go about it. Sorry. Regarding how to download the images locally before sending them to CV, here are some similar questions/answers: https://stackoverflow.com/questions/44588402/how-can-i-read-an-image-from-azure-blob-storage-directly-using-opencv-without-do https://stackoverflow.com/questions/55170572/use-python-to-process-images-in-azure-blob-storage – Tyson Jul 18 '20 at 02:03

2 Answers2

2

Two simple options:

  • Not recommended: Set your blob container to "public" and simply use the full blob urls as you would use any other public URL.
  • Recommended: Construct SAS tokens for your files in blob storage. Append them to the full blob URL to create a "temporary private download link" which can be used to download the file as if it was public. You can also build the link outside of the CV service if you face any issues there.

A full blob URL with a SAS token should look something like this:

https://storagesamples.blob.core.windows.net/sample-container/blob1.txt?se=2019-08-03&sp=rw&sv=2018-11-09&sr=b&skoid=<skoid>&sktid=<sktid>&skt=2019-08-02T2
2%3A32%3A01Z&ske=2019-08-03T00%3A00%3A00Z&sks=b&skv=2018-11-09&sig=<signature>

https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/storage/azure-storage-blob/samples/blob_samples_authentication.py#L110

        # Instantiate a BlobServiceClient using a connection string
        from azure.storage.blob import BlobServiceClient
        blob_service_client = BlobServiceClient.from_connection_string(self.connection_string)

        # [START create_sas_token]
        # Create a SAS token to use to authenticate a new client
        from datetime import datetime, timedelta
        from azure.storage.blob import ResourceTypes, AccountSasPermissions, generate_account_sas

        sas_token = generate_account_sas(
            blob_service_client.account_name,
            account_key=blob_service_client.credential.account_key,
            resource_types=ResourceTypes(object=True),
            permission=AccountSasPermissions(read=True),
            expiry=datetime.utcnow() + timedelta(hours=1)
        )
        # [END create_sas_token]
Alex AIT
  • 17,361
  • 3
  • 36
  • 73
  • So simple! Thanks for the code. At first I avoided your answer until I realized I don't really want to download the files. Getting the SAS token was a lot simpler than it looked, especially since you did all the work for us. – M T Mar 14 '23 at 14:34
1

If you check the sample:

from azure.storage.blob import BlobClient

blob = BlobClient.from_connection_string(conn_str="my_connection_string", container_name="my_container", blob_name="my_blob")

with open("./BlockDestination.txt", "wb") as my_blob:
    blob_data = blob.download_blob()
    blob_data.readinto(my_blob)

all you need to do is get a byte array from my_blob

rather than

Read the image into a byte array

image_data = open(image_path, "rb").read()

you should

Read from the byte array

image_data = my_blob.tobytes()
Thiago Custodio
  • 17,332
  • 6
  • 45
  • 90