I'd like to create a simple Python app recognizing face emotions from given URL via Azure Face/Emotions API.
I'm following this documentation:
https://learn.microsoft.com/en-us/azure/cognitive-services/face/quickstarts/python-sdk#authenticate-the-client
https://learn.microsoft.com/en-us/python/api/azure-cognitiveservices-vision-face/azure.cognitiveservices.vision.face.models.emotion?view=azure-python
So, far, I did the face recognition part, but I'm kinda stuck how to call the Emotion model and display results.
import urllib.request
from azure.cognitiveservices.vision.face import FaceClient
from azure.cognitiveservices.vision.face.models import Emotion
from msrest.authentication import CognitiveServicesCredentials
# Image
URL = "https://upload.wikimedia.org/wikipedia/commons/5/55/Dalailama1_20121014_4639.jpg"
# API
KEY = "xxx"
ENDPOINT = "https://happyai.cognitiveservices.azure.com/"
# Now there is a trained endpoint that can be used to make a prediction
predictor = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))
detected_faces = predictor.face.detect_with_url(url=URL)
if not detected_faces:
raise Exception('No face detected from image {}'.format(URL))
# Display the detected face ID in the first single-face image.
# Face IDs are used for comparison to faces (their IDs) detected in other images.
print('Detected face ID from', URL, ':')
for face in detected_faces: print (face.face_id)
print()
# Save this ID for use in Find Similar
first_image_face_ID = detected_faces[0].face_id
# Call Emotion model
# Display the results.
Any help would be greatly appreciated.
Thanks!
You can use the following code to do the emotion detection,
def det_emotion(self, frame, count):
image_path = self.path_folder + "/img/frame%d.jpg" % count
image_data = open(image_path, "rb")
params = {
'returnFaceId': 'true',
'returnFaceLandmarks': 'false',
'returnRecognitionModel':'false',
}
response = requests.post(self.face_api_url, params=params,data=image_data)
response.raise_for_status()
faces = response.json()
frame = self.add_square(frame, faces)
return frame
in order to get the emotion in return, you need to specifically define the 'emotion' attribute you want to return in the "return_face_attributes" of the 'detect_with_url' function. Please refer to the following code:
face_attributes = ['emotion']
detected_faces = predictor.face.detect_with_url(url=URL, return_face_attributes=face_attributes)
Then when you loop through all the detected faces, you can reach the Emotion object of each face by calling:
for face in detected_faces:
emotionObject = face.face_attributes.emotion
The emotionObject contains 8 different emotions: 'anger', 'contempt', 'disgust', 'fear', 'happiness', 'neutral', 'sadness', 'surprise'.
Since the emotionObject is not an iterable object, and I don't know how to get just the emotion with the highest confident, so I wrote a sub function to convert it into a dictionary type and add it into the face iteration loop:
def get_emotion(emoObject):
emoDict = dict()
emoDict['anger'] = emoObject.anger
emoDict['contempt'] = emoObject.contempt
emoDict['disgust'] = emoObject.disgust
emoDict['fear'] = emoObject.fear
emoDict['happiness'] = emoObject.happiness
emoDict['neutral'] = emoObject.neutral
emoDict['sadness'] = emoObject.sadness
emoDict['surprise'] = emoObject.surprise
emo_name = max(emoDict, key=emoDict.get)
emo_level = emoDict[emo_name]
return emo_name, emo_level
for face in detected_emotional_faces:
emotion, confidence = get_emotion(face.face_attributes.emotion)
print("{} emotion with confidence level {}".format(emotion, confidence))
Related
I want blend multiple satellite images. but an error occured. I followed the example on the satpy document.
here is code and netcdf file is here : https://drive.google.com/drive/folders/1zp6EBVfjuh41LDRRZo4PJoeGGGn13AKy?usp=sharing
from glob import glob
from satpy import Scene, MultiScene, DataQuery
from satpy.utils import debug_on
debug_on()
areaid = 'worldeqc3km70'
eumetsat = glob('E:/Global/combine_test/MSG4-SEVI-MSG15-0100-NA-20210801000010.306000000Z-20210801001259-4774254.nat')
goes17 = glob('E:/Global/combine_test/OR_ABI-L1b-RadF-M6C13_G17_s20212130000319_e20212130009396_c20212130009445.nc')
gk2a = glob('E:/Global/combine_test/gk2a_ami_le1b_ir105_fd020ge_202108010000.nc')
goes17_scene = Scene(reader="abi_l1b", filenames=goes17)
eumetsat_scene = Scene(reader="seviri_l1b_native", filenames=eumetsat)
gk2a_scene = Scene(reader="ami_l1b", filenames=gk2a)
goes17_scene.load(["C13"])
eumetsat_scene.load(['IR_108'])
gk2a_scene.load(["IR105"])
mscn = MultiScene([goes17_scene, eumetsat_scene, gk2a_scene])
#groups = {DataQuery(name='IR_group', wavelength=(9.8, 10.8, 11.8)): ['C13', 'IR105', 'IR_108']}
groups = {DataQuery(name="IR_group", wavelength=(10, 11, 12)): ['C13', 'IR_108', 'IR105']}
mscn.group(groups)
print(mscn.loaded_dataset_ids)
resampled = mscn.resample(areaid, reduce_data=False)
blended = resampled.blend()
blended.save_datasets(filename='./test_{area}.png'.format(area=areaid))
Error message:
RuntimeError: None of the requested datasets have been generated or could not be loaded. Requested composite inputs may need to have matching dimensions (eg. through resampling).
As mentioned in the comments this is a known bug that will hopefully be fixed in the next couple weeks. Follow issue 2089 for more information.
The short-term workaround is to make your own "blend" method that handles things the way you expect:
from satpy.multiscene import stack
def my_blend(mscn, common_datasets, blend_function=stack):
new_scn = Scene()
for ds_id in common_datasets:
datasets = [scn[ds_id] for scn in mscn.scenes if ds_id in scn]
new_scn[ds_id] = blend_function(datasets)
return new_scn
blended = my_blend(resampled, ["ir_group"])
I wanted to use Cloud Vision API to detect labels from ca. 40K photographs and download the results as CSV files. I uploaded photos into the cloud storage and used the following code, but the error occured. I asked a person who uses python in his job but he cannot deal with this error. Can you help mi with fixing it?
TypeError: Invalid constructor input for BatchAnnotateImagesRequest: [{'image': source {
image_uri: "gs://bucket/image-path.jpg"
}
, 'features': [{'type': <Type.LABEL_DETECTION: 4>}]}]
The code I used:
from google.cloud import
from google.cloud import storage
from google.cloud.vision_v1 import ImageAnnotatorClient
from google.cloud.vision_v1 import types
import os
import json
import numpy as np
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]='C://file-path.json'
#(created in step 1)
# Get GCS bucket
storage_client = storage.Client()
bucket = storage_client.bucket('bucket_name')
image_paths = []
for blob in list(bucket.list_blobs()):
image_paths.append("gs://bucket_name/"+blob.name)
# We can send a maximum of 16 images per request.
start = 0
end = 16
label_output = []
for i in range(int(np.floor(len(image_paths)/16))+1):
requests = []
client = vision.ImageAnnotatorClient()
for image_path in image_paths[start:end]:
image = types.Image()
image.source.image_uri = image_path
requests.append({'image': image,'features': [{'type': vision.Feature.Type.LABEL_DETECTION}]})
response = client.batch_annotate_images(requests)
for image_path, i in zip(image_paths[start:end], response.responses):
labels = [{label.description: label.score} for label in i.label_annotations]
labels = {k: v for d in labels for k, v in d.items()}
filename = os.path.basename(image_path)
l = {'filename': filename, 'labels': labels}
label_output.append(l)
start = start+16
end = end+16
#export results to CSV file
for l in label_output:
print('"' + label_output[l]['filename'] + '";', end = '')
for label in label_output[l]["labels"]:
print('"' + label + '";"' + label_output[l][label] + '";', end = '')
print("")
batch_annotate_images() is not getting the contents of requests properly. To fix this, just assign your variable requests explicitly to the parameter requests of batch_annotate_images().
response = client.batch_annotate_images(requests=requests)
See batch_annotate_images() for reference. Also if you are planning to update your Vision API to 2.3.1, you might encounter errors on features: see this reference for the updated usage of its parameters.
I recently started using Google's vision API. I am trying to annotate a batch of images and therefore issued the 'batch image annotation offline' guide from their documentation.
However, it is not clear to me how I can annotate MULTIPLE images from one API call. So let's say I have stored 10 images in my google cloud bucket. How can I annotate all these images at once and store them in one JSON file? Right now, I wrote a program that calls their example function and it works, but to put it simple, why can't I say: 'Look in this folder and annotate all images in it.'?
Thanks in advance.
from batch_image_labeling import sample_async_batch_annotate_images
counter = 0
for file in os.listdir('my_directory'):
filename = file
sample_async_batch_annotate_images('gs://my_bucket/{}'.format(filename), 'gs://my_bucket/{}'.format(counter))
counter += 1
from google.cloud import vision_v1
from google.cloud.vision_v1 import enums
import six
def sample_async_batch_annotate_images(input_image_uri, output_uri):
"""Perform async batch image annotation"""
client = vision_v1.ImageAnnotatorClient()
if isinstance(input_image_uri, six.binary_type):
input_image_uri = input_image_uri.decode('utf-8')
if isinstance(output_uri, six.binary_type):
output_uri = output_uri.decode('utf-8')
source = {'image_uri': input_image_uri}
image = {'source': source}
type_ = enums.Feature.Type.LABEL_DETECTION
features_element = {'type': type_}
type_2 = enums.Feature.Type.IMAGE_PROPERTIES
features_element_2 = {'type': type_2}
features = [features_element, features_element_2]
requests_element = {'image': image, 'features': features}
requests = [requests_element]
gcs_destination = {'uri': output_uri}
# The max number of responses to output in each JSON file
batch_size = 2
output_config = {'gcs_destination': gcs_destination, 'batch_size': batch_size}
operation = client.async_batch_annotate_images(requests, output_config)
print('Waiting for operation to complete...')
response = operation.result()
# The output is written to GCS with the provided output_uri as prefix
gcs_output_uri = response.output_config.gcs_destination.uri
print('Output written to GCS with prefix: {}'.format(gcs_output_uri))
It's somewhat unclear from that example, but your call to async_batch_annotate_images takes a requests parameter which is a list of multiple requests. So you can do something like this:
rom google.cloud import vision_v1
from google.cloud.vision_v1 import enums
import six
def generate_request(input_image_uri):
if isinstance(input_image_uri, six.binary_type):
input_image_uri = input_image_uri.decode('utf-8')
if isinstance(output_uri, six.binary_type):
output_uri = output_uri.decode('utf-8')
source = {'image_uri': input_image_uri}
image = {'source': source}
type_ = enums.Feature.Type.LABEL_DETECTION
features_element = {'type': type_}
type_2 = enums.Feature.Type.IMAGE_PROPERTIES
features_element_2 = {'type': type_2}
features = [features_element, features_element_2]
requests_element = {'image': image, 'features': features}
return requests_element
def sample_async_batch_annotate_images(input_uri, output_uri):
"""Perform async batch image annotation"""
client = vision_v1.ImageAnnotatorClient()
requests = [
generate_request(input_uri.format(filename))
for filename in os.listdir('my_directory')
]
gcs_destination = {'uri': output_uri}
# The max number of responses to output in each JSON file
batch_size = 1
output_config = {'gcs_destination': gcs_destination, 'batch_size': batch_size}
operation = client.async_batch_annotate_images(requests, output_config)
print('Waiting for operation to complete...')
response = operation.result()
# The output is written to GCS with the provided output_uri as prefix
gcs_output_uri = response.output_config.gcs_destination.uri
print('Output written to GCS with prefix: {}'.format(gcs_output_uri))
sample_async_batch_annotate_images('gs://my_bucket/{}', 'gs://my_bucket/results')
This can annotate up to 2,000 images in a single request. The only downside is that you can only specify a single output_uri as a destination, so you won't be able to use counter to put each result in a separate file, but you can set batch_size = 1 to ensure each response is written separately if this is what you want.
I'm currently using google vision's text_detection API for single images but I want to get batch responses. I attempted using BatchAnnotateImagesRequest, but I haven't got it working as of yet.
What i'm doing for getting a response for one image.
client = vision.ImageAnnotatorClient()
with io.open(path, 'rb') as image_file:
content = image_file.read()
image = vision.types.Image(content=content)
response = client.document_text_detection(image=image)
texts = response.text_annotations
There's information regarding batch requests to Google's text detection API in the public documentation.
In the documentation you can find some samples written in python you could use to do batch requests, with a limit of 2000 files per batch:
from google.cloud import vision_v1
from google.cloud.vision_v1 import enums
import six
def sample_async_batch_annotate_images(input_image_uri, output_uri):
"""Perform async batch image annotation"""
client = vision_v1.ImageAnnotatorClient()
# input_image_uri = 'gs://cloud-samples-data/vision/label/wakeupcat.jpg'
# output_uri = 'gs://your-bucket/prefix/'
if isinstance(input_image_uri, six.binary_type):
input_image_uri = input_image_uri.decode('utf-8')
if isinstance(output_uri, six.binary_type):
output_uri = output_uri.decode('utf-8')
source = {'image_uri': input_image_uri}
image = {'source': source}
type_ = enums.Feature.Type.LABEL_DETECTION
features_element = {'type': type_}
type_2 = enums.Feature.Type.IMAGE_PROPERTIES
features_element_2 = {'type': type_2}
features = [features_element, features_element_2]
requests_element = {'image': image, 'features': features}
requests = [requests_element]
gcs_destination = {'uri': output_uri}
# The max number of responses to output in each JSON file
batch_size = 2
output_config = {'gcs_destination': gcs_destination, 'batch_size': batch_size}
operation = client.async_batch_annotate_images(requests, output_config)
print('Waiting for operation to complete...')
response = operation.result()
# The output is written to GCS with the provided output_uri as prefix
gcs_output_uri = response.output_config.gcs_destination.uri
print('Output written to GCS with prefix: {}'.format(gcs_output_uri))
Along the sample code you can also find sample of the output you can expect when executing the batched request. More information regarding batch requests can be found here.
I'm working with the Google Vision API.
I would like to get the vertices ((x,y) locations) of the rectangles where google vision found a block of words. So far I'm getting the text from the google client.
credentials = service_account.Credentials.from_service_account_file("/api-key.json")
client = vision.ImageAnnotatorClient(credentials=credentials)
#open file
with io.open(path, 'rb') as image_file:
content = image_file.read()
#call api
image = types.Image(content=content)
response = client.document_text_detection(image=image)
document = response.full_text_annotation
What I would like is to get the vertices for each block of words in document.text.
It seems like Google has updated the documentation, although it is not so easy to find.
See tutorial on the Google Vision API here
The vertices can be found in response.text_annotations
From google documentation, you can find how the API response is structured (BLOCK, PARAGRAPH, ...) and how to retrieve corresponding vertices.
Particularly this function:
def get_document_bounds(image_file, feature):
"""Returns document bounds given an image."""
client = vision.ImageAnnotatorClient()
bounds = []
with io.open(image_file, 'rb') as image_file:
content = image_file.read()
image = types.Image(content=content)
response = client.document_text_detection(image=image)
document = response.full_text_annotation
# Collect specified feature bounds by enumerating all document features
for page in document.pages:
for block in page.blocks:
for paragraph in block.paragraphs:
for word in paragraph.words:
for symbol in word.symbols:
if (feature == FeatureType.SYMBOL):
bounds.append(symbol.bounding_box)
if (feature == FeatureType.WORD):
bounds.append(word.bounding_box)
if (feature == FeatureType.PARA):
bounds.append(paragraph.bounding_box)
if (feature == FeatureType.BLOCK):
bounds.append(block.bounding_box)
if (feature == FeatureType.PAGE):
bounds.append(block.bounding_box)
# The list `bounds` contains the coordinates of the bounding boxes.
return bounds