0

I have a pre-trained keras model which I have hosted on AWS using AWS SageMaker. I've got an endpoint and I can make successful predictions using the Amazon SageMaker Notebook instance.

What I do there is that I serve a .PNG image like the following and the model gives me correct prediction.

file= s3.Bucket(bucketname).download_file(filename_1, 'normal.png') file_name_1='normal.png' import sagemaker from sagemaker.tensorflow.model import TensorFlowModel endpoint = 'tensorflow-inference-0000-11-22-33-44-55-666' #endpoint predictor=sagemaker.tensorflow.model.TensorFlowPredictor(endpoint, sagemaker_session) data = np.array([resize(imread(file_name), (137, 310, 3))]) predictor.predict(data) 

Now I wanted to make predictions using a mobile application. For that I wrote a Lambda function in python and attached an API gateway to it. My Lambda function is the following.

import os import sys CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(CWD, "lib")) import json import base64 import boto3 import numpy as np from scipy import signal from scipy.signal import butter, lfilter from scipy.io import wavfile import scipy.signal as sps import io from io import BytesIO import matplotlib.pylab as plt from matplotlib import pyplot as plt import matplotlib.image as mpimg from datetime import datetime from skimage.io import imread from skimage.transform import resize from PIL import Image ENDPOINT_NAME = 'tensorflow-inference-0000-11-22-33-44-55-666' runtime= boto3.client('runtime.sagemaker') def lambda_handler(event, context): s3 = boto3.client("s3") # retrieving data from event. get_file_content_from_postman = event["content"] # decoding data. decoded_file_name = base64.b64decode(get_file_content_from_postman) image = Image.open(io.BytesIO(decoded_file_name)) data = np.array([resize(imread(image), (137, 310, 3))]) response = runtime.invoke_endpoint(EndpointName=ENDPOINT_NAME, ContentType='text/csv', Body=data) result = json.loads(response['Body'].read().decode()) return result 

The third last line is giving me error 'PngImageFile' object has no attribute 'read'. Any idea what I am missing here?

2 Answers 2

1

If io.BytesIO(decoded_file_name) correctly represents your image data (though the name decoded_file_name suggests that its only file name, not actual image data), then you don't need to use PIL. Just use it directly:

data = np.array([resize(imread(io.BytesIO(decoded_file_name)), (137, 310, 3))]) 
Sign up to request clarification or add additional context in comments.

2 Comments

Yes I've checked io.BytesIO(decoded_file_name) is representing image data. The problem is that when I make the request via API Gateway then it gives me error which is "Parameter validation failed:\nInvalid type for parameter Body, value: [[[[0.25353752 0.39823243 0.91831497]\n [0.25353752 0.39823243 0.91831497]\n ... type: <class 'numpy.ndarray'>, valid types: <class 'bytes'>, <class 'bytearray'>, file-like object"
@MuhammadArsalanHassan This is new issue. As I wrote before, you probably have multiple issues. Since your example is not-reproducible, you can only solve them one-by-one, rather then all at once.
0

I was missing one thing which was causing this error. After receiving the image data I used python list and then json.dump that list (of lists). Below is the code for reference.

import os import sys CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(CWD, "lib")) import json import base64 import boto3 import numpy as np import io from io import BytesIO from skimage.io import imread from skimage.transform import resize # grab environment variable of Lambda Function ENDPOINT_NAME = os.environ['ENDPOINT_NAME'] runtime= boto3.client('runtime.sagemaker') def lambda_handler(event, context): s3 = boto3.client("s3") # retrieving data from event. get_file_content_from_postman = event["content"] # decoding data. decoded_file_name = base64.b64decode(get_file_content_from_postman) data = np.array([resize(imread(io.BytesIO(decoded_file_name)), (137, 310, 3))]) payload = json.dumps(data.tolist()) response = runtime.invoke_endpoint(EndpointName=ENDPOINT_NAME, ContentType='application/json', Body=payload) result = json.loads(response['Body'].read().decode()) return result 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.