如何在Google Clound AI平台中用Base64服务Tensorflow2图像分割模型。

问题描述 投票:0回答:1

我通过下面的代码成功地将一个TF2图像分割模型保存并部署到AI平台。

@tf.function(input_signature=[tf.TensorSpec(shape=(None), dtype=tf.string)])
def serving(input_image):

    # Convert bytes of jpeg input to float32 tensor for model
    def _input_to_feature(image_bytes):
        img = tf.image.decode_jpeg(image_bytes, channels=3)
        img = tf.image.convert_image_dtype(img, tf.float32) / 255.0
        img = tf.image.resize_with_pad(img, 256, 256)
        return img
    img = tf.map_fn(_input_to_feature, input_image, dtype=tf.float32)

    # Predict
    pred = model(img)

    def _pred_to_image(pred):
        pred = tf.cast(pred * 255, dtype=tf.uint8)

        img_str = tf.image.encode_png(pred, compression=-1, name=None)
        return img_str

    img_str = tf.map_fn(_pred_to_image, pred, dtype=tf.string)

    return img_str


tf.saved_model.save(model, export_dir=checkpoint_dir+'/saved_model', signatures=serving)

但是我在发送这样的请求时得到了这个错误。

img_str = base64.b64encode(open('sample_372.jpg', "rb").read()).decode()
response = service.projects().predict(name=name,body={'instances': [img_str]}).execute()
HttpError: <HttpError 400 when requesting https://ml.googleapis.com/v1/projects/nerveblox-268109/models/femoral/versions/v6:predict?alt=json returned "{ "error": "Expected image (JPEG, PNG, or GIF), got unknown format starting with \'/9j/4AAQSkZJRgAB\'\n\t [[{{node DecodeJpeg}}]]" }">

有人遇到过类似的问题吗?tf.image.decode_jpeg. 我还试着用 tf.image.decode_image 并得到一个类似的错误。我可以用 tf.image.decode_jpeg 用我的本地Base64编码,所以这个函数应该可以工作,但不知为何它在服务器中没有收到相同的输入!我成功地将一个TF2图像分割模型保存并部署到AI平台,并使用了以下代码。

google-cloud-platform tensorflow2.0 tensorflow-serving gcp-ai-platform-training
1个回答
1
投票

经过大量的实验(由于Tensorflow的文档有限且过时),我意识到为了让服务函数解码Base64,请求应该这样发送。{'instances': [{'b64': image_base64}]}. 此外,我还发现,为了让服务函数解码Base64,请求应该这样发送: . convert_image_dtype 自己将数据缩放到[0,1],所以255.0不应该做。另外 map_fn 只在CPU上工作,所以它应该和 with tf.device('/cpu:0'):. 最后,最烦人的部分是编码到Base64。tf.io.encode_base64 是我在Tensorflow中找到的唯一一种编码为Base64的方法,但它编码为web-safe,这意味着它将\和+替换为_和-,以便在URL中工作。但Google API客户端只接受普通的Base64编码。所以我不得不用regualr表达式来反转。这是更新后的服务函数。

@tf.function(input_signature=[tf.TensorSpec(shape=(None), dtype=tf.string)])
def serving(input_image):

    # Convert bytes of jpeg input to float32 tensor for model
    def _input_to_feature(img_bytes):
        img = tf.image.decode_image(img_bytes, channels=3)
        img = tf.image.convert_image_dtype(img, tf.float32)
        img = tf.image.resize_with_pad(img, 256, 256)
        return img

    # Preprocessing
    with tf.device('/cpu:0'):
        img = tf.map_fn(_input_to_feature, input_image, dtype=tf.float32)

    # Prediction
    with tf.device('/gpu:0'):
        pred = model(img)
        colors = tf.constant([[0.2, 0.3, 0.4]])
        pred_rgb = tf.tensordot(pred, colors, axes=1)

    def _pred_to_image(pred):
        pred = tf.image.convert_image_dtype(pred,dtype=tf.uint8)

        pred_str = tf.image.encode_png(pred, compression=4)
        pred_encoded = tf.io.encode_base64(pred_str, pad=True)
        pred_encoded = tf.strings.regex_replace(pred_encoded, '_', '/')
        pred_encoded = tf.strings.regex_replace(pred_encoded, '-', '+')

        return pred_encoded

    # Postprocessing
    with tf.device('/cpu:0'):
        img_str = tf.map_fn(_pred_to_image, pred_rgb, dtype=tf.string)

    return img_str


tf.saved_model.save(model, export_dir=checkpoint_dir+'/saved_model', signatures=serving)

0
投票

我意识到它也可以不使用 tf.map_fn 像这样。

# Prediction
with tf.device('/gpu'):
    img = tf.image.decode_image(input_image[0], channels=3)

    img = tf.image.convert_image_dtype(img, tf.float32)
    img = tf.expand_dims(img, axis=0)
    pred = model(img)[0]
    colors = tf.constant([[0, 0, 0],
                          [1., 0, 0],
                          [0, 1., 0],
                          [0, 0, 1.],
                          [1., 1., 0]
                         ])
    pred_rgb = tf.tensordot(pred, colors, axes=1)

    not_background = pred[...,0][...,None] < 0.9
    transparency = tf.cast(not_background, dtype=tf.float32)*0.3

    rgba = tf.concat((pred_rgb, transparency), axis=-1)
    rgba = tf.image.convert_image_dtype(rgba, dtype=tf.uint8)

    pred_str = tf.image.encode_png(rgba, compression=5)
    pred_encoded = tf.io.encode_base64(pred_str, pad=True)
    pred_encoded = tf.strings.regex_replace(pred_encoded, '_', '/')
    pred_encoded = tf.strings.regex_replace(pred_encoded, '-', '+')
    pred_encoded = tf.expand_dims(pred_encoded, axis=0)

return pred_encoded
© www.soinside.com 2019 - 2024. All rights reserved.