私の理解では、GoogleのAIハブからTensorFlowモデルを取得し、それをTensorFlow Servingにデプロイして、curlを使用してRESTリクエストを介して画像をPOSTすることで予測を行うことができます。
現時点ではAI Hubでbbox予測子を見つけることができませんでしたが、TensorFlowモデルZooで予測子を見つけました。
http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz
TensorFlowサービングにモデルをデプロイしましたが、RESTリクエストのJSONに何を含める必要があるかについて、ドキュメントは明確ではありません。
私の理解は
私は次のようにモデルの署名定義を取得することができました:
>python tensorflow/tensorflow/python/tools/saved_model_cli.py show --dir /Users/alexryan/Alpine/git/tfserving-tutorial3/model-volume/models/bbox/1/ --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:
signature_def['serving_default']:
The given SavedModel SignatureDef contains the following input(s):
inputs['in'] tensor_info:
dtype: DT_UINT8
shape: (-1, -1, -1, 3)
name: image_tensor:0
The given SavedModel SignatureDef contains the following output(s):
outputs['out'] tensor_info:
dtype: DT_FLOAT
shape: unknown_rank
name: detection_boxes:0
Method name is: tensorflow/serving/predict
ここの形状情報を考えるモデルがあらゆる次元の画像を処理できることを私に伝えていますか?
Tensorboardでは、入力レイヤーは次のようになります。
しかし、このSignatureDefinitionを有効なJSONリクエストに変換するにはどうすればよいですか?
predict APIを使用することになっていると想定しています...
そして Googleのドキュメント は...
URL
POST http:// Host:port/v1/models / $ {MODEL_NAME} [/ versions/$ {MODEL_VERSION}]:predict
/ versions/$ {MODEL_VERSION}はオプションです。省略した場合、最新バージョンが使用されます。
リクエストフォーマット
predict APIのリクエスト本文は、次の形式のJSONオブジェクトである必要があります:{ // (Optional) Serving signature to use. // If unspecifed default serving signature is used. "signature_name": <string>, // Input Tensors in row ("instances") or columnar ("inputs") format. // A request can have either of them but NOT both. "instances": <value>|<(nested)list>|<list-of-objects> "inputs": <value>|<(nested)list>|<object> }
バイナリ値のエンコードJSONはUTF-8エンコードを使用します。 (画像のバイトのように)バイナリである必要がある入力特徴またはテンソル値がある場合、Base64でデータをエンコードし、次のようにb64をキーとして持つJSONオブジェクトにカプセル化する必要があります。
{ "b64": "base64 encoded string" }
このオブジェクトを入力特徴またはテンソルの値として指定できます。同じ形式が出力応答のエンコードにも使用されます。
画像(バイナリデータ)とキャプション機能を含む分類要求を以下に示します。
{ "signature_name": "classify_objects", "examples": [
{
"image": { "b64": "aW1hZ2UgYnl0ZXM=" },
"caption": "seaside"
},
{
"image": { "b64": "YXdlc29tZSBpbWFnZSBieXRlcw==" },
"caption": "mountains"
} ] }
不確実性は次のとおりです。
TensorFlow-ServingのRESTful APIを使用した画像ベースのディープラーニングモデルの提供 この形式が推奨されます:
{
"instances": [
{"b64": "iVBORw"},
{"b64": "pT4rmN"},
{"b64": "w0KGg2"}
]
}
私はこの画像を使用しました: https://tensorflow.org/images/blogs/serving/cat.jpg
そしてbase64はそれを次のようにエンコードしました:
# Download the image
dl_request = requests.get(IMAGE_URL, stream=True)
dl_request.raise_for_status()
# Compose a JSON Predict request (send JPEG image in base64).
jpeg_bytes = base64.b64encode(dl_request.content).decode('utf-8')
predict_request = '{"instances" : [{"b64": "%s"}]}' % jpeg_bytes
しかし、私がcurlをPOSTに使用すると、base64でエンコードされた画像は次のようになります。
{"instances" : [{"b64": "/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAA
...
KACiiigAooooAKKKKACiiigAooooA//Z"}]}
私はこのような応答を受け取ります:
>./test_local_tfs.sh
HEADER=|Content-Type:application/json;charset=UTF-8|
URL=|http://127.0.0.1:8501/v1/models/saved_model/versions/1:predict|
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8501 (#0)
> POST /v1/models/saved_model/versions/1:predict HTTP/1.1
> Host: 127.0.0.1:8501
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type:application/json;charset=UTF-8
> Content-Length: 85033
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Date: Tue, 17 Sep 2019 10:47:18 GMT
< Content-Length: 85175
<
{ "error": "Failed to process element: 0 of \'instances\' list. Error: Invalid argument: JSON Value: {\n \"b64\": \"/9j/4AAQSkZJRgABAQAAS
...
ooooA//Z\"\n} Type: Object is not of expected type: uint8" }
同じファイルのローカルバージョンをbase64に変換してみました(dtypeがuint8であることを確認しています)...
img = cv2.imread('cat.jpg')
print('dtype: ' + str(img.dtype))
_, buf = cv2.imencode('.jpg', img)
jpeg_bytes = base64.b64encode(buf).decode('utf-8')
predict_request = '{"instances" : [{"b64": "%s"}]}' % jpeg_bytes
しかし、このJSONをポストすると同じエラーが発生します。
しかし、jsonがそのようにフォーマットされている場合...
{'instances': [[[[112, 71, 48], [104, 63, 40], [107, 70, 20], [108, 72, 21], [109, 77, 0], [106, 75, 0], [92, 66, 0], [106, 80, 0], [101, 80, 0], [98, 77, 0], [100, 75, 0], [104, 80, 0], [114, 88, 17], [94, 68, 0], [85, 54, 0], [103, 72, 11], [93, 62, 0], [120, 89, 25], [131, 101, 37], [125, 95, 31], [119, 91, 27], [121, 93, 29], [133, 105, 40], [119, 91, 27], [119, 96, 56], [120, 97, 57], [119, 96, 53], [102, 78, 36], [132, 103, 44], [117, 88, 28], [125, 89, 4], [128, 93, 8], [133, 94, 0], [126, 87, 0], [110, 74, 0], [123, 87, 2], [120, 92, 30], [124, 95, 33], [114, 90, 32],
...
, [43, 24, 33], [30, 17, 36], [24, 11, 30], [29, 20, 38], [37, 28, 46]]]]}
... できます。問題は、このjsonファイルのサイズが11 MBを超えることです。
Jsonのbase64エンコードバージョンを機能させるにはどうすればよいですか?
更新:入力レイヤーでbase64画像を受け入れるように事前トレーニング済みモデルを編集する必要があるようです
この記事では、モデルを編集する方法について説明します... メディア:TensorFlow-ServingのRESTful APIを使用した画像ベースのディープラーニングモデルの提供 ...残念ながら、これは、モデル。
user260826のソリューションは、推定器を使用した回避策を提供しますが、モデルがケラスモデルであることを前提としています。この場合は当てはまりません。
TensorFlow Servingのモデルを準備するための一般的な方法はありますかREST TensorFlowモデル形式のいずれかで機能するbase64エンコード画像とのインターフェース?
最初のステップは、トレーニング済みモデルを適切な形式でエクスポートすることです。このように export_inference_graph.py を使用します
python export_inference_graph \
--input_type encoded_image_string_tensor \
--pipeline_config_path path/to/ssd_inception_v2.config \
--trained_checkpoint_prefix path/to/model.ckpt \
--output_directory path/to/exported_model_directory
上記のコードスニペットでは、指定することが重要です
--input_type encrypted_image_string_tensor
モデルをエクスポートした後、新しくエクスポートされたモデルを使用して、通常どおりtensorflowサーバーを実行します。
推論コードは次のようになります。
from __future__ import print_function
import base64
import requests
SERVER_URL = 'http://localhost:8501/v1/models/vedNet:predict'
IMAGE_URL = 'test_images/19_inp.jpg'
def main():
with open(IMAGE_URL, "rb") as image_file:
jpeg_bytes = base64.b64encode(image_file.read()).decode('utf-8')
predict_request = '{"instances" : [{"b64": "%s"}]}' % jpeg_bytes
response = requests.post(SERVER_URL, predict_request)
response.raise_for_status()
prediction = response.json()['predictions'][0]
if __name__ == '__main__':
main()