0

I'm running a detectron2 instance segmention with a AWS endpoint, I used this tutorial [https://github.com/aws-samples/amazon-sagemaker-pytorch-detectron2][1] for Object Detection, and I adapted to instance segmentation and worked well, but to draw the masks and object identification I need to do it outside the endpoint, inside the endpoint I only have the model(pth file) and the settings(yml file) in a script. And I would like to do everything from the endpoint, just get the final result, that is the segmented image.

UPDATE

I have my_script.py on an Endpoint:

from sqlalchemy import true
from detectron2 import model_zoo
from detectron2.config import get_cfg
from detectron2.engine import DefaultPredictor
from detectron2.data import MetadataCatalog
from detectron2.utils.visualizer import Visualizer, ColorMode
import matplotlib.pyplot as plt
import cv2
import numpy as np
import math
from PIL import Image
import scipy.cluster
import sklearn.cluster
import os
import sys
from typing import BinaryIO, Mapping
import json
import logging
from pathlib import Path
from json import JSONEncoder
import torch

##############
# Macros
##############

LOGGER = logging.Logger("InferenceScript", level=logging.INFO)
HANDLER = logging.StreamHandler(sys.stdout)
HANDLER.setFormatter(logging.Formatter("%(levelname)s | %(name)s | %(message)s"))
LOGGER.addHandler(HANDLER)

static_prefix = os.path.join(os.getcwd(), './')
log_file = os.path.join(static_prefix, 'latest')

##########
# Deploy
##########
def _load_from_bytearray(request_body: BinaryIO) -> np.ndarray:
    npimg = np.frombuffer(request_body, np.uint8)
    return cv2.imdecode(npimg, cv2.IMREAD_COLOR)

class NumpyArrayEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return JSONEncoder.default(self, obj)
        
def  model_fn(model_dir: str) -> DefaultPredictor:
    path_cfg = "/opt/ml/model/config.yml"
    path_model = "/opt/ml/model/model_final"
    print('config= ',  path_cfg) 
    print('modelo=',path_model)
    os.system("ls")
    LOGGER.info(f"Using configuration specified in {path_cfg}")
    LOGGER.info(f"Using model saved at {path_model}")
    
    if path_model is None:
        err_msg = "Missing model PTH file"
        LOGGER.error(err_msg)
        raise RuntimeError(err_msg)
    if path_cfg is None:
        err_msg = "Missing configuration JSON file"
        LOGGER.error(err_msg)
        raise RuntimeError(err_msg)
    
    cfg = get_cfg()
    cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 
    cfg.merge_from_file(path_cfg)
    cfg.MODEL.WEIGHTS = str(path_model)
    cfg.DATALOADER.NUM_WORKERS = 2
    cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128 
    cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3
    cfg.MODEL.DEVICE = "cpu"
   
    LOGGER.info(f"model_loader ={cfg}")
    predictorReturn = DefaultPredictor(cfg)
    modelStr = predictorReturn.model

    LOGGER.info(f"model_arqtuiteture ={modelStr}")
    LOGGER.info(f"model_fn - end")
    return predictorReturn


def input_fn(request_body: BinaryIO, request_content_type: str) -> np.ndarray:
    LOGGER.info(f"*input_fn - init*")
    if request_content_type == "application/x-image":
        np_image = _load_from_bytearray(request_body)
    else:
        err_msg = f"Type [{request_content_type}] not support this type yet"
        LOGGER.error(err_msg)
        raise ValueError(err_msg)
    LOGGER.info(f"*input_fn - end*")
    return np_image

def predict_fn(input_object: np.ndarray, predictor: DefaultPredictor) -> Mapping:
    LOGGER.info(f"Prediction on image of shape {input_object.shape}")
    normalizedImg = np.zeros((1000, 1000))
    input_object = cv2.cvtColor(np.ndarray(input_object), cv2.COLOR_RGB2BGR)
    input_object = cv2.normalize(input_object,normalizedImg, 0, 255, cv2.NORM_MINMAX) 
    cfg = get_cfg()
    predictor = DefaultPredictor(cfg)
    outputs = predictor(input_object)
    
    MetadataCatalog.get(cfg.DATASETS.TRAIN[0]).thing_classes = ["t1","t2","t3"]
    v = Visualizer(input_object[:, :, ::-1], metadata=MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), instance_mode=ColorMode.IMAGE_BW)
    out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
    
    fmt_out= cv2.cvtColor(out.get_image()[:, :, ::-1], cv2.COLOR_RGBA2RGB)
    classes = outputs["instances"].pred_classes.tolist() 

    print('obj:',len(classes))
    print('classes:' ,len(set(classes)))
    return fmt_out

def output_fn(predictions, response_content_type):
    LOGGER.info(f"*output_fn init - end*")
    jsonPredictions =json.dumps(predictions)
    LOGGER.info(f"after jsonPredictions dumps ")
    return jsonPredictions

To run this, I tried this code in my jupyter notebook:

import boto3
    
endpoint_name="my_endpoint"
client = boto3.client('sagemaker-runtime')
content_type = 'application/x-image'
accept_mime_type = 'application/x-image'


with open("my_image.jpg", "rb") as f:
  payload = bytearray(f.read())
##############################

response = client.invoke_endpoint(
    EndpointName=endpoint_name,
    Accept=accept_mime_type,
    ContentType=content_type,
    Body=payload,
)

# Write segmented output image
with open("my_image.segmented.jpg", "wb") as f:
    f.write(response["Body"].read())

I used the above code as a hunch, I got his code here ([https://extrapolations.dev/model/instance-segmentation-mask-r-cnn/api/#examples][2]). And now I got this error:

ModelError: An error occurred (ModelError) when calling the InvokeEndpoint operation: Received server error (500) from primary and could not load the entire response body.

I think is a problem in my format input. Some suggestion?

Curious G.
  • 838
  • 8
  • 23

1 Answers1

1

Can you add loggers in each of your handler functions? This will help us capture which function is leading to the error in your inference script, you can view these results in the CloudWatch Logs. To debug more quickly I suggest two methods:

  1. Host the container using Docker so you don't need to deploy an endpoint each time and wait to debug.

  2. Utilize SageMaker Local Mode (takes care of option 1 for you for a lot of use-cases), ex: https://towardsdatascience.com/debugging-sagemaker-endpoints-quickly-with-local-mode-2975bd55f6f7

Ram Vegiraju
  • 399
  • 2
  • 5